rnd-20040928-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 void getGraphicSource(int graphic, int frame, Bitmap **bitmap, int *x, int *y)
945 {
946   struct GraphicInfo *g = &graphic_info[graphic];
947
948   *bitmap = g->bitmap;
949
950   if (g->offset_y == 0)         /* frames are ordered horizontally */
951   {
952     int max_width = g->anim_frames_per_line * g->width;
953
954     *x = (g->src_x + frame * g->offset_x) % max_width;
955     *y = g->src_y + (g->src_x + frame * g->offset_x) / max_width * g->height;
956   }
957   else if (g->offset_x == 0)    /* frames are ordered vertically */
958   {
959     int max_height = g->anim_frames_per_line * g->height;
960
961     *x = g->src_x + (g->src_y + frame * g->offset_y) / max_height * g->width;
962     *y = (g->src_y + frame * g->offset_y) % max_height;
963   }
964   else                          /* frames are ordered diagonally */
965   {
966     *x = g->src_x + frame * g->offset_x;
967     *y = g->src_y + frame * g->offset_y;
968   }
969 }
970
971 void DrawGraphic(int x, int y, int graphic, int frame)
972 {
973 #if DEBUG
974   if (!IN_SCR_FIELD(x, y))
975   {
976     printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
977     printf("DrawGraphic(): This should never happen!\n");
978     return;
979   }
980 #endif
981
982   DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic, frame);
983   MarkTileDirty(x, y);
984 }
985
986 void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
987                     int frame)
988 {
989   Bitmap *src_bitmap;
990   int src_x, src_y;
991
992   getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
993   BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
994 }
995
996 void DrawGraphicThruMask(int x, int y, int graphic, int frame)
997 {
998 #if DEBUG
999   if (!IN_SCR_FIELD(x, y))
1000   {
1001     printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
1002     printf("DrawGraphicThruMask(): This should never happen!\n");
1003     return;
1004   }
1005 #endif
1006
1007   DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY, graphic,
1008                          frame);
1009   MarkTileDirty(x, y);
1010 }
1011
1012 void DrawGraphicThruMaskExt(DrawBuffer *d, int dest_x, int dest_y, int graphic,
1013                             int frame)
1014 {
1015 #if 1
1016   Bitmap *src_bitmap;
1017   int src_x, src_y;
1018   GC drawing_gc;
1019
1020   getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1021   drawing_gc = src_bitmap->stored_clip_gc;
1022 #else
1023   GC drawing_gc = src_bitmap->stored_clip_gc;
1024   Bitmap *src_bitmap = graphic_info[graphic].bitmap;
1025   int src_x = graphic_info[graphic].src_x;
1026   int src_y = graphic_info[graphic].src_y;
1027   int offset_x = graphic_info[graphic].offset_x;
1028   int offset_y = graphic_info[graphic].offset_y;
1029
1030   src_x += frame * offset_x;
1031   src_y += frame * offset_y;
1032
1033 #endif
1034
1035   SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1036   BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dest_x, dest_y);
1037 }
1038
1039 void DrawMiniGraphic(int x, int y, int graphic)
1040 {
1041   DrawMiniGraphicExt(drawto, SX + x * MINI_TILEX,SY + y * MINI_TILEY, graphic);
1042   MarkTileDirty(x / 2, y / 2);
1043 }
1044
1045 void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1046 {
1047   struct GraphicInfo *g = &graphic_info[graphic];
1048   int mini_startx = 0;
1049   int mini_starty = g->bitmap->height * 2 / 3;
1050
1051   *bitmap = g->bitmap;
1052   *x = mini_startx + g->src_x / 2;
1053   *y = mini_starty + g->src_y / 2;
1054 }
1055
1056 void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
1057 {
1058   Bitmap *src_bitmap;
1059   int src_x, src_y;
1060
1061   getMiniGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1062   BlitBitmap(src_bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
1063 }
1064
1065 void DrawGraphicShifted(int x, int y, int dx, int dy, int graphic, int frame,
1066                         int cut_mode, int mask_mode)
1067 {
1068   Bitmap *src_bitmap;
1069   GC drawing_gc;
1070   int src_x, src_y;
1071   int width = TILEX, height = TILEY;
1072   int cx = 0, cy = 0;
1073   int dest_x, dest_y;
1074
1075   if (graphic < 0)
1076   {
1077     DrawGraphic(x, y, graphic, frame);
1078     return;
1079   }
1080
1081   if (dx || dy)                 /* shifted graphic */
1082   {
1083     if (x < BX1)                /* object enters playfield from the left */
1084     {
1085       x = BX1;
1086       width = dx;
1087       cx = TILEX - dx;
1088       dx = 0;
1089     }
1090     else if (x > BX2)           /* object enters playfield from the right */
1091     {
1092       x = BX2;
1093       width = -dx;
1094       dx = TILEX + dx;
1095     }
1096     else if (x==BX1 && dx < 0)  /* object leaves playfield to the left */
1097     {
1098       width += dx;
1099       cx = -dx;
1100       dx = 0;
1101     }
1102     else if (x==BX2 && dx > 0)  /* object leaves playfield to the right */
1103       width -= dx;
1104     else if (dx)                /* general horizontal movement */
1105       MarkTileDirty(x + SIGN(dx), y);
1106
1107     if (y < BY1)                /* object enters playfield from the top */
1108     {
1109       if (cut_mode==CUT_BELOW)  /* object completely above top border */
1110         return;
1111
1112       y = BY1;
1113       height = dy;
1114       cy = TILEY - dy;
1115       dy = 0;
1116     }
1117     else if (y > BY2)           /* object enters playfield from the bottom */
1118     {
1119       y = BY2;
1120       height = -dy;
1121       dy = TILEY + dy;
1122     }
1123     else if (y==BY1 && dy < 0)  /* object leaves playfield to the top */
1124     {
1125       height += dy;
1126       cy = -dy;
1127       dy = 0;
1128     }
1129     else if (dy > 0 && cut_mode == CUT_ABOVE)
1130     {
1131       if (y == BY2)             /* object completely above bottom border */
1132         return;
1133
1134       height = dy;
1135       cy = TILEY - dy;
1136       dy = TILEY;
1137       MarkTileDirty(x, y + 1);
1138     }                           /* object leaves playfield to the bottom */
1139     else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1140       height -= dy;
1141     else if (dy)                /* general vertical movement */
1142       MarkTileDirty(x, y + SIGN(dy));
1143   }
1144
1145 #if 1
1146   getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1147 #else
1148   src_bitmap = graphic_info[graphic].bitmap;
1149   src_x = graphic_info[graphic].src_x;
1150   src_y = graphic_info[graphic].src_y;
1151   offset_x = graphic_info[graphic].offset_x;
1152   offset_y = graphic_info[graphic].offset_y;
1153
1154   src_x += frame * offset_x;
1155   src_y += frame * offset_y;
1156 #endif
1157
1158   drawing_gc = src_bitmap->stored_clip_gc;
1159
1160   src_x += cx;
1161   src_y += cy;
1162
1163   dest_x = FX + x * TILEX + dx;
1164   dest_y = FY + y * TILEY + dy;
1165
1166 #if DEBUG
1167   if (!IN_SCR_FIELD(x,y))
1168   {
1169     printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1170     printf("DrawGraphicShifted(): This should never happen!\n");
1171     return;
1172   }
1173 #endif
1174
1175   if (mask_mode == USE_MASKING)
1176   {
1177     SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1178     BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
1179                      dest_x, dest_y);
1180   }
1181   else
1182     BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1183                dest_x, dest_y);
1184
1185   MarkTileDirty(x, y);
1186 }
1187
1188 void DrawGraphicShiftedThruMask(int x, int y, int dx, int dy, int graphic,
1189                                 int frame, int cut_mode)
1190 {
1191   DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, USE_MASKING);
1192 }
1193
1194 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1195                           int cut_mode, int mask_mode)
1196 {
1197   int lx = LEVELX(x), ly = LEVELY(y);
1198   int graphic;
1199   int frame;
1200
1201   if (IN_LEV_FIELD(lx, ly))
1202   {
1203     SetRandomAnimationValue(lx, ly);
1204
1205     graphic = el_act_dir2img(element, GfxAction[lx][ly], GfxDir[lx][ly]);
1206     frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
1207   }
1208   else  /* border element */
1209   {
1210     graphic = el2img(element);
1211     frame = getGraphicAnimationFrame(graphic, -1);
1212   }
1213
1214   if (element == EL_EXPANDABLE_WALL)
1215   {
1216     boolean left_stopped = FALSE, right_stopped = FALSE;
1217
1218     if (!IN_LEV_FIELD(lx - 1, ly) || IS_WALL(Feld[lx - 1][ly]))
1219       left_stopped = TRUE;
1220     if (!IN_LEV_FIELD(lx + 1, ly) || IS_WALL(Feld[lx + 1][ly]))
1221       right_stopped = TRUE;
1222
1223     if (left_stopped && right_stopped)
1224       graphic = IMG_WALL;
1225     else if (left_stopped)
1226     {
1227       graphic = IMG_EXPANDABLE_WALL_GROWING_RIGHT;
1228       frame = graphic_info[graphic].anim_frames - 1;
1229     }
1230     else if (right_stopped)
1231     {
1232       graphic = IMG_EXPANDABLE_WALL_GROWING_LEFT;
1233       frame = graphic_info[graphic].anim_frames - 1;
1234     }
1235   }
1236
1237   if (dx || dy)
1238     DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
1239   else if (mask_mode == USE_MASKING)
1240     DrawGraphicThruMask(x, y, graphic, frame);
1241   else
1242     DrawGraphic(x, y, graphic, frame);
1243 }
1244
1245 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1246                          int cut_mode, int mask_mode)
1247 {
1248   if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1249     DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1250                          cut_mode, mask_mode);
1251 }
1252
1253 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1254                               int cut_mode)
1255 {
1256   DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1257 }
1258
1259 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1260                              int cut_mode)
1261 {
1262   DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1263 }
1264
1265 void DrawLevelElementThruMask(int x, int y, int element)
1266 {
1267   DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1268 }
1269
1270 void DrawLevelFieldThruMask(int x, int y)
1271 {
1272   DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1273 }
1274
1275 #define TILE_GFX_ELEMENT(x, y)                                              \
1276         (GfxElement[x][y] != EL_UNDEFINED && Feld[x][y] != EL_EXPLOSION ?   \
1277          GfxElement[x][y] : Feld[x][y])
1278
1279 static void DrawLevelFieldCrumbledSandExt(int x, int y, int graphic, int frame)
1280 {
1281   Bitmap *src_bitmap;
1282   int src_x, src_y;
1283   int sx = SCREENX(x), sy = SCREENY(y);
1284   int element;
1285   int width, height, cx, cy, i;
1286 #if 1
1287   int crumbled_border_size = graphic_info[graphic].border_size;
1288 #else
1289   int snip = TILEX / 8; /* number of border pixels from "crumbled graphic" */
1290 #endif
1291   static int xy[4][2] =
1292   {
1293     { 0, -1 },
1294     { -1, 0 },
1295     { +1, 0 },
1296     { 0, +1 }
1297   };
1298
1299 #if 0
1300   if (x == 0 && y == 7)
1301     printf("::: %d, %d [%d]\n", GfxElement[x][y], Feld[x][y],
1302            crumbled_border_size);
1303 #endif
1304
1305   if (!IN_LEV_FIELD(x, y))
1306     return;
1307
1308   element = TILE_GFX_ELEMENT(x, y);
1309
1310   /* crumble field itself */
1311   if (GFX_CRUMBLED(element) && !IS_MOVING(x, y))
1312   {
1313     if (!IN_SCR_FIELD(sx, sy))
1314       return;
1315
1316     getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1317
1318     for (i = 0; i < 4; i++)
1319     {
1320       int xx = x + xy[i][0];
1321       int yy = y + xy[i][1];
1322
1323 #if 1
1324       element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
1325                  BorderElement);
1326 #else
1327       element = (IN_LEV_FIELD(xx, yy) ? Feld[xx][yy] : BorderElement);
1328 #endif
1329
1330       /* check if neighbour field is of same type */
1331       if (GFX_CRUMBLED(element) && !IS_MOVING(xx, yy))
1332         continue;
1333
1334 #if 0
1335       if (Feld[x][y] == EL_CUSTOM_START + 123)
1336         printf("::: crumble [%d] THE CHAOS ENGINE (%d, %d): %d, %d\n",
1337                i, Feld[x][y], element,
1338                GFX_CRUMBLED(element), IS_MOVING(x, y));
1339 #endif
1340
1341       if (i == 1 || i == 2)
1342       {
1343         width = crumbled_border_size;
1344         height = TILEY;
1345         cx = (i == 2 ? TILEX - crumbled_border_size : 0);
1346         cy = 0;
1347       }
1348       else
1349       {
1350         width = TILEX;
1351         height = crumbled_border_size;
1352         cx = 0;
1353         cy = (i == 3 ? TILEY - crumbled_border_size : 0);
1354       }
1355
1356       BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1357                  width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
1358     }
1359
1360     MarkTileDirty(sx, sy);
1361   }
1362   else          /* crumble neighbour fields */
1363   {
1364 #if 0
1365     getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1366 #endif
1367
1368     for (i = 0; i < 4; i++)
1369     {
1370       int xx = x + xy[i][0];
1371       int yy = y + xy[i][1];
1372       int sxx = sx + xy[i][0];
1373       int syy = sy + xy[i][1];
1374
1375 #if 1
1376       if (!IN_LEV_FIELD(xx, yy) ||
1377           !IN_SCR_FIELD(sxx, syy) ||
1378           IS_MOVING(xx, yy))
1379         continue;
1380
1381       element = TILE_GFX_ELEMENT(xx, yy);
1382
1383       if (!GFX_CRUMBLED(element))
1384         continue;
1385 #else
1386       if (!IN_LEV_FIELD(xx, yy) ||
1387           !IN_SCR_FIELD(sxx, syy) ||
1388           !GFX_CRUMBLED(Feld[xx][yy]) ||
1389           IS_MOVING(xx, yy))
1390         continue;
1391 #endif
1392
1393 #if 1
1394       graphic = el_act2crm(Feld[xx][yy], ACTION_DEFAULT);
1395       crumbled_border_size = graphic_info[graphic].border_size;
1396
1397       getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1398 #endif
1399
1400       if (i == 1 || i == 2)
1401       {
1402         width = crumbled_border_size;
1403         height = TILEY;
1404         cx = (i == 1 ? TILEX - crumbled_border_size : 0);
1405         cy = 0;
1406       }
1407       else
1408       {
1409         width = TILEX;
1410         height = crumbled_border_size;
1411         cx = 0;
1412         cy = (i == 0 ? TILEY - crumbled_border_size : 0);
1413       }
1414
1415       BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1416                  width, height, FX + sxx * TILEX + cx, FY + syy * TILEY + cy);
1417
1418       MarkTileDirty(sxx, syy);
1419     }
1420   }
1421 }
1422
1423 void DrawLevelFieldCrumbledSand(int x, int y)
1424 {
1425 #if 1
1426   int graphic;
1427
1428   if (!IN_LEV_FIELD(x, y))
1429     return;
1430
1431   graphic = el_act2crm(Feld[x][y], ACTION_DEFAULT);
1432
1433   DrawLevelFieldCrumbledSandExt(x, y, graphic, 0);
1434 #else
1435   DrawLevelFieldCrumbledSandExt(x, y, IMG_SAND_CRUMBLED, 0);
1436 #endif
1437 }
1438
1439 void DrawLevelFieldCrumbledSandDigging(int x, int y, int direction,
1440                                        int step_frame)
1441 {
1442 #if 1
1443   int graphic1 = el_act_dir2img(GfxElement[x][y], ACTION_DIGGING, direction);
1444   int graphic2 = el_act_dir2crm(GfxElement[x][y], ACTION_DIGGING, direction);
1445 #else
1446   int graphic1 = el_act_dir2img(EL_SAND,          ACTION_DIGGING, direction);
1447   int graphic2 = el_act_dir2img(EL_SAND_CRUMBLED, ACTION_DIGGING, direction);
1448 #endif
1449   int frame1 = getGraphicAnimationFrame(graphic1, step_frame);
1450   int frame2 = getGraphicAnimationFrame(graphic2, step_frame);
1451   int sx = SCREENX(x), sy = SCREENY(y);
1452
1453   DrawGraphic(sx, sy, graphic1, frame1);
1454   DrawLevelFieldCrumbledSandExt(x, y, graphic2, frame2);
1455 }
1456
1457 void DrawLevelFieldCrumbledSandNeighbours(int x, int y)
1458 {
1459   int sx = SCREENX(x), sy = SCREENY(y);
1460   static int xy[4][2] =
1461   {
1462     { 0, -1 },
1463     { -1, 0 },
1464     { +1, 0 },
1465     { 0, +1 }
1466   };
1467   int i;
1468
1469   for (i = 0; i < 4; i++)
1470   {
1471     int xx = x + xy[i][0];
1472     int yy = y + xy[i][1];
1473     int sxx = sx + xy[i][0];
1474     int syy = sy + xy[i][1];
1475
1476     if (!IN_LEV_FIELD(xx, yy) ||
1477         !IN_SCR_FIELD(sxx, syy) ||
1478         !GFX_CRUMBLED(Feld[xx][yy]) ||
1479         IS_MOVING(xx, yy))
1480       continue;
1481
1482     DrawLevelField(xx, yy);
1483   }
1484 }
1485
1486 static int getBorderElement(int x, int y)
1487 {
1488   int border[7][2] =
1489   {
1490     { EL_STEELWALL_TOPLEFT,             EL_INVISIBLE_STEELWALL_TOPLEFT     },
1491     { EL_STEELWALL_TOPRIGHT,            EL_INVISIBLE_STEELWALL_TOPRIGHT    },
1492     { EL_STEELWALL_BOTTOMLEFT,          EL_INVISIBLE_STEELWALL_BOTTOMLEFT  },
1493     { EL_STEELWALL_BOTTOMRIGHT,         EL_INVISIBLE_STEELWALL_BOTTOMRIGHT },
1494     { EL_STEELWALL_VERTICAL,            EL_INVISIBLE_STEELWALL_VERTICAL    },
1495     { EL_STEELWALL_HORIZONTAL,          EL_INVISIBLE_STEELWALL_HORIZONTAL  },
1496     { EL_STEELWALL,                     EL_INVISIBLE_STEELWALL             }
1497   };
1498   int steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
1499   int steel_position = (x == -1         && y == -1              ? 0 :
1500                         x == lev_fieldx && y == -1              ? 1 :
1501                         x == -1         && y == lev_fieldy      ? 2 :
1502                         x == lev_fieldx && y == lev_fieldy      ? 3 :
1503                         x == -1         || x == lev_fieldx      ? 4 :
1504                         y == -1         || y == lev_fieldy      ? 5 : 6);
1505
1506   return border[steel_position][steel_type];
1507 }
1508
1509 void DrawScreenElement(int x, int y, int element)
1510 {
1511   DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1512   DrawLevelFieldCrumbledSand(LEVELX(x), LEVELY(y));
1513 }
1514
1515 void DrawLevelElement(int x, int y, int element)
1516 {
1517   if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1518     DrawScreenElement(SCREENX(x), SCREENY(y), element);
1519 }
1520
1521 void DrawScreenField(int x, int y)
1522 {
1523   int lx = LEVELX(x), ly = LEVELY(y);
1524   int element, content;
1525
1526   if (!IN_LEV_FIELD(lx, ly))
1527   {
1528     if (lx < -1 || lx > lev_fieldx || ly < -1 || ly > lev_fieldy)
1529       element = EL_EMPTY;
1530     else
1531       element = getBorderElement(lx, ly);
1532
1533     DrawScreenElement(x, y, element);
1534     return;
1535   }
1536
1537   element = Feld[lx][ly];
1538   content = Store[lx][ly];
1539
1540   if (IS_MOVING(lx, ly))
1541   {
1542     int horiz_move = (MovDir[lx][ly] == MV_LEFT || MovDir[lx][ly] == MV_RIGHT);
1543     boolean cut_mode = NO_CUTTING;
1544
1545     if (element == EL_QUICKSAND_EMPTYING ||
1546         element == EL_MAGIC_WALL_EMPTYING ||
1547         element == EL_BD_MAGIC_WALL_EMPTYING ||
1548         element == EL_AMOEBA_DROPPING)
1549       cut_mode = CUT_ABOVE;
1550     else if (element == EL_QUICKSAND_FILLING ||
1551              element == EL_MAGIC_WALL_FILLING ||
1552              element == EL_BD_MAGIC_WALL_FILLING)
1553       cut_mode = CUT_BELOW;
1554
1555     if (cut_mode == CUT_ABOVE)
1556       DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1557     else
1558       DrawScreenElement(x, y, EL_EMPTY);
1559
1560     if (horiz_move)
1561       DrawScreenElementShifted(x, y, MovPos[lx][ly], 0, element, NO_CUTTING);
1562     else if (cut_mode == NO_CUTTING)
1563       DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], element, cut_mode);
1564     else
1565       DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], content, cut_mode);
1566
1567     if (content == EL_ACID)
1568     {
1569       int dir = MovDir[lx][ly];
1570       int newlx = lx + (dir == MV_LEFT ? -1 : dir == MV_RIGHT ? +1 : 0);
1571       int newly = ly + (dir == MV_UP   ? -1 : dir == MV_DOWN  ? +1 : 0);
1572
1573       DrawLevelElementThruMask(newlx, newly, EL_ACID);
1574     }
1575   }
1576   else if (IS_BLOCKED(lx, ly))
1577   {
1578     int oldx, oldy;
1579     int sx, sy;
1580     int horiz_move;
1581     boolean cut_mode = NO_CUTTING;
1582     int element_old, content_old;
1583
1584     Blocked2Moving(lx, ly, &oldx, &oldy);
1585     sx = SCREENX(oldx);
1586     sy = SCREENY(oldy);
1587     horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1588                   MovDir[oldx][oldy] == MV_RIGHT);
1589
1590     element_old = Feld[oldx][oldy];
1591     content_old = Store[oldx][oldy];
1592
1593     if (element_old == EL_QUICKSAND_EMPTYING ||
1594         element_old == EL_MAGIC_WALL_EMPTYING ||
1595         element_old == EL_BD_MAGIC_WALL_EMPTYING ||
1596         element_old == EL_AMOEBA_DROPPING)
1597       cut_mode = CUT_ABOVE;
1598
1599     DrawScreenElement(x, y, EL_EMPTY);
1600
1601     if (horiz_move)
1602       DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
1603                                NO_CUTTING);
1604     else if (cut_mode == NO_CUTTING)
1605       DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
1606                                cut_mode);
1607     else
1608       DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
1609                                cut_mode);
1610   }
1611   else if (IS_DRAWABLE(element))
1612     DrawScreenElement(x, y, element);
1613   else
1614     DrawScreenElement(x, y, EL_EMPTY);
1615 }
1616
1617 void DrawLevelField(int x, int y)
1618 {
1619   if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1620     DrawScreenField(SCREENX(x), SCREENY(y));
1621   else if (IS_MOVING(x, y))
1622   {
1623     int newx,newy;
1624
1625     Moving2Blocked(x, y, &newx, &newy);
1626     if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1627       DrawScreenField(SCREENX(newx), SCREENY(newy));
1628   }
1629   else if (IS_BLOCKED(x, y))
1630   {
1631     int oldx, oldy;
1632
1633     Blocked2Moving(x, y, &oldx, &oldy);
1634     if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1635       DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1636   }
1637 }
1638
1639 void DrawMiniElement(int x, int y, int element)
1640 {
1641   int graphic;
1642
1643   graphic = el2edimg(element);
1644   DrawMiniGraphic(x, y, graphic);
1645 }
1646
1647 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1648 {
1649   int x = sx + scroll_x, y = sy + scroll_y;
1650
1651   if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1652     DrawMiniElement(sx, sy, EL_EMPTY);
1653   else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1654     DrawMiniElement(sx, sy, Feld[x][y]);
1655   else
1656     DrawMiniGraphic(sx, sy, el2edimg(getBorderElement(x, y)));
1657 }
1658
1659 void DrawEnvelopeBackground(int envelope_nr, int startx, int starty,
1660                             int x, int y, int xsize, int ysize, int font_nr)
1661 {
1662   int font_width  = getFontWidth(font_nr);
1663   int font_height = getFontHeight(font_nr);
1664   int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1665   Bitmap *src_bitmap;
1666   int src_x, src_y;
1667   int dst_x = SX + startx + x * font_width;
1668   int dst_y = SY + starty + y * font_height;
1669   int width  = graphic_info[graphic].width;
1670   int height = graphic_info[graphic].height;
1671   int inner_width  = MAX(width  - 2 * font_width,  font_width);
1672   int inner_height = MAX(height - 2 * font_height, font_height);
1673   int inner_sx = (width >= 3 * font_width ? font_width : 0);
1674   int inner_sy = (height >= 3 * font_height ? font_height : 0);
1675   boolean draw_masked = graphic_info[graphic].draw_masked;
1676
1677   getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
1678
1679   if (src_bitmap == NULL || width < font_width || height < font_height)
1680   {
1681     ClearRectangle(drawto, dst_x, dst_y, font_width, font_height);
1682     return;
1683   }
1684
1685   src_x += (x == 0 ? 0 : x == xsize - 1 ? width  - font_width  :
1686             inner_sx + (x - 1) * font_width  % inner_width);
1687   src_y += (y == 0 ? 0 : y == ysize - 1 ? height - font_height :
1688             inner_sy + (y - 1) * font_height % inner_height);
1689
1690   if (draw_masked)
1691   {
1692     SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1693                   dst_x - src_x, dst_y - src_y);
1694     BlitBitmapMasked(src_bitmap, drawto, src_x, src_y, font_width, font_height,
1695                      dst_x, dst_y);
1696   }
1697   else
1698     BlitBitmap(src_bitmap, drawto, src_x, src_y, font_width, font_height,
1699                dst_x, dst_y);
1700 }
1701
1702 void AnimateEnvelope(int envelope_nr, int anim_mode, int action)
1703 {
1704   int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1705 #if 1
1706   Bitmap *src_bitmap = graphic_info[graphic].bitmap;
1707   int mask_mode = (src_bitmap != NULL ? BLIT_MASKED : BLIT_ON_BACKGROUND);
1708 #else
1709   boolean draw_masked = graphic_info[graphic].draw_masked;
1710   int mask_mode = (draw_masked ? BLIT_MASKED : BLIT_ON_BACKGROUND);
1711 #endif
1712   boolean ffwd_delay = (tape.playing && tape.fast_forward);
1713   boolean no_delay = (tape.warp_forward);
1714   unsigned long anim_delay = 0;
1715   int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
1716   int anim_delay_value = (no_delay ? 0 : frame_delay_value);
1717   int font_nr = FONT_ENVELOPE_1 + envelope_nr;
1718   int font_width = getFontWidth(font_nr);
1719   int font_height = getFontHeight(font_nr);
1720   int max_xsize = level.envelope_xsize[envelope_nr];
1721   int max_ysize = level.envelope_ysize[envelope_nr];
1722   int xstart = (anim_mode & ANIM_VERTICAL ? max_xsize : 0);
1723   int ystart = (anim_mode & ANIM_HORIZONTAL ? max_ysize : 0);
1724   int xend = max_xsize;
1725   int yend = (anim_mode != ANIM_DEFAULT ? max_ysize : 0);
1726   int xstep = (xstart < xend ? 1 : 0);
1727   int ystep = (ystart < yend || xstep == 0 ? 1 : 0);
1728   int x, y;
1729
1730   for (x = xstart, y = ystart; x <= xend && y <= yend; x += xstep, y += ystep)
1731   {
1732     int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2;
1733     int ysize = (action == ACTION_CLOSING ? yend - (y - ystart) : y) + 2;
1734     int sx = (SXSIZE - xsize * font_width)  / 2;
1735     int sy = (SYSIZE - ysize * font_height) / 2;
1736     int xx, yy;
1737
1738     SetDrawtoField(DRAW_BUFFERED);
1739
1740     BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
1741
1742     SetDrawtoField(DRAW_BACKBUFFER);
1743
1744     for (yy = 0; yy < ysize; yy++) for (xx = 0; xx < xsize; xx++)
1745       DrawEnvelopeBackground(envelope_nr, sx,sy, xx,yy, xsize, ysize, font_nr);
1746
1747     DrawTextToTextArea(SX + sx + font_width, SY + sy + font_height,
1748                        level.envelope_text[envelope_nr], font_nr, max_xsize,
1749                        xsize - 2, ysize - 2, mask_mode);
1750
1751     redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
1752     BackToFront();
1753
1754     WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
1755   }
1756 }
1757
1758 void ShowEnvelope(int envelope_nr)
1759 {
1760   int element = EL_ENVELOPE_1 + envelope_nr;
1761   int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1762   int sound_opening = element_info[element].sound[ACTION_OPENING];
1763   int sound_closing = element_info[element].sound[ACTION_CLOSING];
1764   boolean ffwd_delay = (tape.playing && tape.fast_forward);
1765   boolean no_delay = (tape.warp_forward);
1766   int normal_delay_value = ONE_SECOND_DELAY / (ffwd_delay ? 2 : 1);
1767   int wait_delay_value = (no_delay ? 0 : normal_delay_value);
1768   int anim_mode = graphic_info[graphic].anim_mode;
1769   int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL:
1770                         anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode);
1771
1772   game.envelope_active = TRUE;  /* needed for RedrawPlayfield() events */
1773
1774   PlaySoundStereo(sound_opening, SOUND_MIDDLE);
1775
1776   if (anim_mode == ANIM_DEFAULT)
1777     AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_OPENING);
1778
1779   AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_OPENING);
1780
1781   if (tape.playing)
1782     Delay(wait_delay_value);
1783   else
1784     WaitForEventToContinue();
1785
1786   PlaySoundStereo(sound_closing, SOUND_MIDDLE);
1787
1788   if (anim_mode != ANIM_NONE)
1789     AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_CLOSING);
1790
1791   if (anim_mode == ANIM_DEFAULT)
1792     AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_CLOSING);
1793
1794   game.envelope_active = FALSE;
1795
1796   SetDrawtoField(DRAW_BUFFERED);
1797
1798   redraw_mask |= REDRAW_FIELD;
1799   BackToFront();
1800 }
1801
1802 void getMicroGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1803 {
1804   Bitmap *src_bitmap = graphic_info[graphic].bitmap;
1805   int mini_startx = src_bitmap->width * 3 / 4;
1806   int mini_starty = src_bitmap->height * 2 / 3;
1807   int src_x = mini_startx + graphic_info[graphic].src_x / 8;
1808   int src_y = mini_starty + graphic_info[graphic].src_y / 8;
1809
1810   *bitmap = src_bitmap;
1811   *x = src_x;
1812   *y = src_y;
1813 }
1814
1815 void DrawMicroElement(int xpos, int ypos, int element)
1816 {
1817   Bitmap *src_bitmap;
1818   int src_x, src_y;
1819   int graphic = el2preimg(element);
1820
1821   getMicroGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1822   BlitBitmap(src_bitmap, drawto, src_x, src_y, MICRO_TILEX, MICRO_TILEY,
1823              xpos, ypos);
1824 }
1825
1826 void DrawLevel()
1827 {
1828   int x,y;
1829
1830   SetDrawBackgroundMask(REDRAW_NONE);
1831   ClearWindow();
1832
1833   for (x = BX1; x <= BX2; x++)
1834     for (y = BY1; y <= BY2; y++)
1835       DrawScreenField(x, y);
1836
1837   redraw_mask |= REDRAW_FIELD;
1838 }
1839
1840 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1841 {
1842   int x,y;
1843
1844   for (x = 0; x < size_x; x++)
1845     for (y = 0; y < size_y; y++)
1846       DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1847
1848   redraw_mask |= REDRAW_FIELD;
1849 }
1850
1851 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1852 {
1853   int x, y;
1854
1855   DrawBackground(xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
1856
1857   if (lev_fieldx < STD_LEV_FIELDX)
1858     xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1859   if (lev_fieldy < STD_LEV_FIELDY)
1860     ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1861
1862   xpos += MICRO_TILEX;
1863   ypos += MICRO_TILEY;
1864
1865   for (x = -1; x <= STD_LEV_FIELDX; x++)
1866   {
1867     for (y = -1; y <= STD_LEV_FIELDY; y++)
1868     {
1869       int lx = from_x + x, ly = from_y + y;
1870
1871       if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1872         DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1873                          level.field[lx][ly]);
1874       else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1
1875                && BorderElement != EL_EMPTY)
1876         DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1877                          getBorderElement(lx, ly));
1878     }
1879   }
1880
1881   redraw_mask |= REDRAW_MICROLEVEL;
1882 }
1883
1884 #define MICROLABEL_EMPTY                0
1885 #define MICROLABEL_LEVEL_NAME           1
1886 #define MICROLABEL_CREATED_BY           2
1887 #define MICROLABEL_LEVEL_AUTHOR         3
1888 #define MICROLABEL_IMPORTED_FROM        4
1889 #define MICROLABEL_LEVEL_IMPORT_INFO    5
1890
1891 static void DrawMicroLevelLabelExt(int mode)
1892 {
1893   char label_text[MAX_OUTPUT_LINESIZE + 1];
1894   int max_len_label_text;
1895   int font_nr = FONT_TEXT_2;
1896
1897   if (mode == MICROLABEL_CREATED_BY || mode == MICROLABEL_IMPORTED_FROM)
1898     font_nr = FONT_TEXT_3;
1899
1900   max_len_label_text = SXSIZE / getFontWidth(font_nr);
1901
1902   DrawBackground(SX, MICROLABEL_YPOS, SXSIZE, getFontHeight(font_nr));
1903
1904   strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
1905                        mode == MICROLABEL_CREATED_BY ? "created by" :
1906                        mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
1907                        mode == MICROLABEL_IMPORTED_FROM ? "imported from" :
1908                        mode == MICROLABEL_LEVEL_IMPORT_INFO ?
1909                        leveldir_current->imported_from : ""),
1910           max_len_label_text);
1911   label_text[max_len_label_text] = '\0';
1912
1913   if (strlen(label_text) > 0)
1914   {
1915     int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
1916     int lypos = MICROLABEL_YPOS;
1917
1918     DrawText(lxpos, lypos, label_text, font_nr);
1919   }
1920
1921   redraw_mask |= REDRAW_MICROLEVEL;
1922 }
1923
1924 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1925 {
1926   static unsigned long scroll_delay = 0;
1927   static unsigned long label_delay = 0;
1928   static int from_x, from_y, scroll_direction;
1929   static int label_state, label_counter;
1930   int last_game_status = game_status;   /* save current game status */
1931
1932   /* force PREVIEW font on preview level */
1933   game_status = GAME_MODE_PSEUDO_PREVIEW;
1934
1935   if (restart)
1936   {
1937     from_x = from_y = 0;
1938     scroll_direction = MV_RIGHT;
1939     label_state = 1;
1940     label_counter = 0;
1941
1942     DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1943     DrawMicroLevelLabelExt(label_state);
1944
1945     /* initialize delay counters */
1946     DelayReached(&scroll_delay, 0);
1947     DelayReached(&label_delay, 0);
1948
1949     if (leveldir_current->name)
1950     {
1951       int text_width = getTextWidth(leveldir_current->name, FONT_TEXT_1);
1952       int lxpos = SX + (SXSIZE - text_width) / 2;
1953       int lypos = SY + 352;
1954
1955       DrawText(lxpos, lypos, leveldir_current->name, FONT_TEXT_1);
1956     }
1957
1958     game_status = last_game_status;     /* restore current game status */
1959
1960     return;
1961   }
1962
1963   /* scroll micro level, if needed */
1964   if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1965       DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1966   {
1967     switch (scroll_direction)
1968     {
1969       case MV_LEFT:
1970         if (from_x > 0)
1971           from_x--;
1972         else
1973           scroll_direction = MV_UP;
1974         break;
1975
1976       case MV_RIGHT:
1977         if (from_x < lev_fieldx - STD_LEV_FIELDX)
1978           from_x++;
1979         else
1980           scroll_direction = MV_DOWN;
1981         break;
1982
1983       case MV_UP:
1984         if (from_y > 0)
1985           from_y--;
1986         else
1987           scroll_direction = MV_RIGHT;
1988         break;
1989
1990       case MV_DOWN:
1991         if (from_y < lev_fieldy - STD_LEV_FIELDY)
1992           from_y++;
1993         else
1994           scroll_direction = MV_LEFT;
1995         break;
1996
1997       default:
1998         break;
1999     }
2000
2001     DrawMicroLevelExt(xpos, ypos, from_x, from_y);
2002   }
2003
2004   /* redraw micro level label, if needed */
2005   if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
2006       strcmp(level.author, ANONYMOUS_NAME) != 0 &&
2007       strcmp(level.author, leveldir_current->name) != 0 &&
2008       DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
2009   {
2010     int max_label_counter = 23;
2011
2012     if (leveldir_current->imported_from != NULL)
2013       max_label_counter += 14;
2014
2015     label_counter = (label_counter + 1) % max_label_counter;
2016     label_state = (label_counter >= 0 && label_counter <= 7 ?
2017                    MICROLABEL_LEVEL_NAME :
2018                    label_counter >= 9 && label_counter <= 12 ?
2019                    MICROLABEL_CREATED_BY :
2020                    label_counter >= 14 && label_counter <= 21 ?
2021                    MICROLABEL_LEVEL_AUTHOR :
2022                    label_counter >= 23 && label_counter <= 26 ?
2023                    MICROLABEL_IMPORTED_FROM :
2024                    label_counter >= 28 && label_counter <= 35 ?
2025                    MICROLABEL_LEVEL_IMPORT_INFO : MICROLABEL_EMPTY);
2026     DrawMicroLevelLabelExt(label_state);
2027   }
2028
2029   game_status = last_game_status;       /* restore current game status */
2030 }
2031
2032 void WaitForEventToContinue()
2033 {
2034   boolean still_wait = TRUE;
2035
2036   /* simulate releasing mouse button over last gadget, if still pressed */
2037   if (button_status)
2038     HandleGadgets(-1, -1, 0);
2039
2040   button_status = MB_RELEASED;
2041
2042   while (still_wait)
2043   {
2044     if (PendingEvent())
2045     {
2046       Event event;
2047
2048       NextEvent(&event);
2049
2050       switch (event.type)
2051       {
2052         case EVENT_BUTTONPRESS:
2053         case EVENT_KEYPRESS:
2054           still_wait = FALSE;
2055           break;
2056
2057         case EVENT_KEYRELEASE:
2058           ClearPlayerAction();
2059           break;
2060
2061         default:
2062           HandleOtherEvents(&event);
2063           break;
2064       }
2065     }
2066     else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2067     {
2068       still_wait = FALSE;
2069     }
2070
2071     DoAnimation();
2072
2073     /* don't eat all CPU time */
2074     Delay(10);
2075   }
2076 }
2077
2078 #define MAX_REQUEST_LINES               13
2079 #define MAX_REQUEST_LINE_FONT1_LEN      7
2080 #define MAX_REQUEST_LINE_FONT2_LEN      10
2081
2082 boolean Request(char *text, unsigned int req_state)
2083 {
2084   int mx, my, ty, result = -1;
2085   unsigned int old_door_state;
2086   int last_game_status = game_status;   /* save current game status */
2087   int max_request_line_len = MAX_REQUEST_LINE_FONT1_LEN;
2088   int font_nr = FONT_TEXT_2;
2089   int max_word_len = 0;
2090   char *text_ptr;
2091
2092   for (text_ptr = text; *text_ptr; text_ptr++)
2093   {
2094     max_word_len = (*text_ptr != ' ' ? max_word_len + 1 : 0);
2095
2096     if (max_word_len > MAX_REQUEST_LINE_FONT1_LEN)
2097     {
2098       max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
2099       font_nr = FONT_LEVEL_NUMBER;
2100
2101       break;
2102     }
2103   }
2104
2105 #if 1
2106   /* disable deactivated drawing when quick-loading level tape recording */
2107   if (tape.playing && tape.deactivate_display)
2108     TapeDeactivateDisplayOff(TRUE);
2109 #endif
2110
2111 #if 1
2112   SetMouseCursor(CURSOR_DEFAULT);
2113 #endif
2114
2115 #if defined(NETWORK_AVALIABLE)
2116   /* pause network game while waiting for request to answer */
2117   if (options.network &&
2118       game_status == GAME_MODE_PLAYING &&
2119       req_state & REQUEST_WAIT_FOR_INPUT)
2120     SendToServer_PausePlaying();
2121 #endif
2122
2123   old_door_state = GetDoorState();
2124
2125   /* simulate releasing mouse button over last gadget, if still pressed */
2126   if (button_status)
2127     HandleGadgets(-1, -1, 0);
2128
2129   UnmapAllGadgets();
2130
2131   if (old_door_state & DOOR_OPEN_1)
2132   {
2133     CloseDoor(DOOR_CLOSE_1);
2134
2135     /* save old door content */
2136     BlitBitmap(bitmap_db_door, bitmap_db_door,
2137                DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
2138                DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
2139   }
2140
2141   SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
2142
2143   /* clear door drawing field */
2144   DrawBackground(DX, DY, DXSIZE, DYSIZE);
2145
2146   /* force DOOR font on preview level */
2147   game_status = GAME_MODE_PSEUDO_DOOR;
2148
2149   /* write text for request */
2150   for (ty = 0; ty < MAX_REQUEST_LINES; ty++)
2151   {
2152     char text_line[max_request_line_len + 1];
2153     int tx, tl, tc = 0;
2154
2155     if (!*text)
2156       break;
2157
2158     for (tl = 0, tx = 0; tx < max_request_line_len; tl++, tx++)
2159     {
2160       tc = *(text + tx);
2161       if (!tc || tc == ' ')
2162         break;
2163     }
2164
2165     if (!tl)
2166     { 
2167       text++; 
2168       ty--; 
2169       continue; 
2170     }
2171
2172     strncpy(text_line, text, tl);
2173     text_line[tl] = 0;
2174
2175     DrawText(DX + (DXSIZE - tl * getFontWidth(font_nr)) / 2,
2176              DY + 8 + ty * (getFontHeight(font_nr) + 2),
2177              text_line, font_nr);
2178
2179     text += tl + (tc == ' ' ? 1 : 0);
2180   }
2181
2182   game_status = last_game_status;       /* restore current game status */
2183
2184   if (req_state & REQ_ASK)
2185   {
2186     MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
2187     MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
2188   }
2189   else if (req_state & REQ_CONFIRM)
2190   {
2191     MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
2192   }
2193   else if (req_state & REQ_PLAYER)
2194   {
2195     MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
2196     MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
2197     MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
2198     MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
2199   }
2200
2201   /* copy request gadgets to door backbuffer */
2202   BlitBitmap(drawto, bitmap_db_door,
2203              DX, DY, DXSIZE, DYSIZE,
2204              DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2205
2206   OpenDoor(DOOR_OPEN_1);
2207
2208 #if 0
2209   ClearEventQueue();
2210 #endif
2211
2212   if (!(req_state & REQUEST_WAIT_FOR_INPUT))
2213   {
2214     SetDrawBackgroundMask(REDRAW_FIELD);
2215
2216     return FALSE;
2217   }
2218
2219   if (game_status != GAME_MODE_MAIN)
2220     InitAnimation();
2221
2222   button_status = MB_RELEASED;
2223
2224   request_gadget_id = -1;
2225
2226   SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
2227
2228 #if 0
2229   SetMouseCursor(CURSOR_DEFAULT);
2230 #endif
2231
2232   while (result < 0)
2233   {
2234     if (PendingEvent())
2235     {
2236       Event event;
2237
2238       NextEvent(&event);
2239
2240       switch(event.type)
2241       {
2242         case EVENT_BUTTONPRESS:
2243         case EVENT_BUTTONRELEASE:
2244         case EVENT_MOTIONNOTIFY:
2245         {
2246           if (event.type == EVENT_MOTIONNOTIFY)
2247           {
2248             if (!PointerInWindow(window))
2249               continue; /* window and pointer are on different screens */
2250
2251             if (!button_status)
2252               continue;
2253
2254             motion_status = TRUE;
2255             mx = ((MotionEvent *) &event)->x;
2256             my = ((MotionEvent *) &event)->y;
2257           }
2258           else
2259           {
2260             motion_status = FALSE;
2261             mx = ((ButtonEvent *) &event)->x;
2262             my = ((ButtonEvent *) &event)->y;
2263             if (event.type == EVENT_BUTTONPRESS)
2264               button_status = ((ButtonEvent *) &event)->button;
2265             else
2266               button_status = MB_RELEASED;
2267           }
2268
2269           /* this sets 'request_gadget_id' */
2270           HandleGadgets(mx, my, button_status);
2271
2272           switch(request_gadget_id)
2273           {
2274             case TOOL_CTRL_ID_YES:
2275               result = TRUE;
2276               break;
2277             case TOOL_CTRL_ID_NO:
2278               result = FALSE;
2279               break;
2280             case TOOL_CTRL_ID_CONFIRM:
2281               result = TRUE | FALSE;
2282               break;
2283
2284             case TOOL_CTRL_ID_PLAYER_1:
2285               result = 1;
2286               break;
2287             case TOOL_CTRL_ID_PLAYER_2:
2288               result = 2;
2289               break;
2290             case TOOL_CTRL_ID_PLAYER_3:
2291               result = 3;
2292               break;
2293             case TOOL_CTRL_ID_PLAYER_4:
2294               result = 4;
2295               break;
2296
2297             default:
2298               break;
2299           }
2300
2301           break;
2302         }
2303
2304         case EVENT_KEYPRESS:
2305           switch(GetEventKey((KeyEvent *)&event, TRUE))
2306           {
2307             case KSYM_Return:
2308               result = 1;
2309               break;
2310
2311             case KSYM_Escape:
2312               result = 0;
2313               break;
2314
2315             default:
2316               break;
2317           }
2318           if (req_state & REQ_PLAYER)
2319             result = 0;
2320           break;
2321
2322         case EVENT_KEYRELEASE:
2323           ClearPlayerAction();
2324           break;
2325
2326         default:
2327           HandleOtherEvents(&event);
2328           break;
2329       }
2330     }
2331     else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2332     {
2333       int joy = AnyJoystick();
2334
2335       if (joy & JOY_BUTTON_1)
2336         result = 1;
2337       else if (joy & JOY_BUTTON_2)
2338         result = 0;
2339     }
2340
2341     DoAnimation();
2342
2343     /* don't eat all CPU time */
2344     Delay(10);
2345   }
2346
2347   if (game_status != GAME_MODE_MAIN)
2348     StopAnimation();
2349
2350   UnmapToolButtons();
2351
2352   if (!(req_state & REQ_STAY_OPEN))
2353   {
2354     CloseDoor(DOOR_CLOSE_1);
2355
2356     if (((old_door_state & DOOR_OPEN_1) && !(req_state & REQ_STAY_CLOSED)) ||
2357         (req_state & REQ_REOPEN))
2358       OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
2359   }
2360
2361   RemapAllGadgets();
2362
2363   SetDrawBackgroundMask(REDRAW_FIELD);
2364
2365 #if defined(NETWORK_AVALIABLE)
2366   /* continue network game after request */
2367   if (options.network &&
2368       game_status == GAME_MODE_PLAYING &&
2369       req_state & REQUEST_WAIT_FOR_INPUT)
2370     SendToServer_ContinuePlaying();
2371 #endif
2372
2373 #if 1
2374   /* restore deactivated drawing when quick-loading level tape recording */
2375   if (tape.playing && tape.deactivate_display)
2376     TapeDeactivateDisplayOn();
2377 #endif
2378
2379   return result;
2380 }
2381
2382 unsigned int OpenDoor(unsigned int door_state)
2383 {
2384   if (door_state & DOOR_COPY_BACK)
2385   {
2386     if (door_state & DOOR_OPEN_1)
2387       BlitBitmap(bitmap_db_door, bitmap_db_door,
2388                  DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
2389                  DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2390
2391     if (door_state & DOOR_OPEN_2)
2392       BlitBitmap(bitmap_db_door, bitmap_db_door,
2393                  DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY2, VXSIZE, VYSIZE,
2394                  DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2395
2396     door_state &= ~DOOR_COPY_BACK;
2397   }
2398
2399   return MoveDoor(door_state);
2400 }
2401
2402 unsigned int CloseDoor(unsigned int door_state)
2403 {
2404   unsigned int old_door_state = GetDoorState();
2405
2406   if (!(door_state & DOOR_NO_COPY_BACK))
2407   {
2408     if (old_door_state & DOOR_OPEN_1)
2409       BlitBitmap(backbuffer, bitmap_db_door,
2410                  DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2411
2412     if (old_door_state & DOOR_OPEN_2)
2413       BlitBitmap(backbuffer, bitmap_db_door,
2414                  VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2415
2416     door_state &= ~DOOR_NO_COPY_BACK;
2417   }
2418
2419   return MoveDoor(door_state);
2420 }
2421
2422 unsigned int GetDoorState()
2423 {
2424   return MoveDoor(DOOR_GET_STATE);
2425 }
2426
2427 unsigned int SetDoorState(unsigned int door_state)
2428 {
2429   return MoveDoor(door_state | DOOR_SET_STATE);
2430 }
2431
2432 unsigned int MoveDoor(unsigned int door_state)
2433 {
2434   static int door1 = DOOR_OPEN_1;
2435   static int door2 = DOOR_CLOSE_2;
2436   unsigned long door_delay = 0;
2437   unsigned long door_delay_value;
2438   int stepsize = 1;
2439
2440   if (door_state == DOOR_GET_STATE)
2441     return(door1 | door2);
2442
2443   if (door_state & DOOR_SET_STATE)
2444   {
2445     if (door_state & DOOR_ACTION_1)
2446       door1 = door_state & DOOR_ACTION_1;
2447     if (door_state & DOOR_ACTION_2)
2448       door2 = door_state & DOOR_ACTION_2;
2449
2450     return(door1 | door2);
2451   }
2452
2453   if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2454     door_state &= ~DOOR_OPEN_1;
2455   else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2456     door_state &= ~DOOR_CLOSE_1;
2457   if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2458     door_state &= ~DOOR_OPEN_2;
2459   else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2460     door_state &= ~DOOR_CLOSE_2;
2461
2462   door_delay_value = (door_state & DOOR_ACTION_1 ? door_1.step_delay :
2463                       door_2.step_delay);
2464
2465   if (setup.quick_doors)
2466   {
2467     stepsize = 20;              /* must be choosen to always draw last frame */
2468     door_delay_value = 0;
2469
2470 #if 0
2471     StopSound(SND_DOOR_OPENING);
2472     StopSound(SND_DOOR_CLOSING);
2473 #endif
2474   }
2475
2476   if (global.autoplay_leveldir)
2477   {
2478     door_state |= DOOR_NO_DELAY;
2479     door_state &= ~DOOR_CLOSE_ALL;
2480   }
2481
2482   if (door_state & DOOR_ACTION)
2483   {
2484     boolean door_1_done = !(door_state & DOOR_ACTION_1);
2485     boolean door_2_done = !(door_state & DOOR_ACTION_2);
2486     int start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2487     int end = (door_state & DOOR_ACTION_1 &&
2488                door_1.anim_mode == ANIM_VERTICAL ? DYSIZE : DXSIZE);
2489     int x;
2490
2491     if (!(door_state & DOOR_NO_DELAY) && !setup.quick_doors)
2492     {
2493       /* opening door sound has priority over simultaneously closing door */
2494       if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
2495         PlaySoundStereo(SND_DOOR_OPENING, SOUND_MIDDLE);
2496       else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
2497         PlaySoundStereo(SND_DOOR_CLOSING, SOUND_MIDDLE);
2498     }
2499
2500     for (x = start; x <= end && !(door_1_done && door_2_done); x += stepsize)
2501     {
2502       Bitmap *bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2503       GC gc = bitmap->stored_clip_gc;
2504
2505       if (door_state & DOOR_ACTION_1)
2506       {
2507         int a = MIN(x * door_1.step_offset, end);
2508         int i = (door_state & DOOR_OPEN_1 ? end - a : a);
2509
2510         if (x <= a)
2511         {
2512           BlitBitmap(bitmap_db_door, drawto,
2513                      DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i / 2,
2514                      DXSIZE, DYSIZE - i / 2, DX, DY);
2515
2516           ClearRectangle(drawto, DX, DY + DYSIZE - i / 2, DXSIZE, i / 2);
2517         }
2518
2519         if (door_1.anim_mode == ANIM_HORIZONTAL && x <= DXSIZE)
2520         {
2521           int src1_x = DXSIZE,          src1_y = DOOR_GFX_PAGEY1;
2522           int dst1_x = DX + DXSIZE - i, dst1_y = DY;
2523           int src2_x = DXSIZE - i,      src2_y = DOOR_GFX_PAGEY1;
2524           int dst2_x = DX,              dst2_y = DY;
2525           int width = i, height = DYSIZE;
2526
2527           SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2528           BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2529                            dst1_x, dst1_y);
2530
2531           SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2532           BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2533                            dst2_x, dst2_y);
2534         }
2535         else if (door_1.anim_mode == ANIM_VERTICAL && x <= DYSIZE)
2536         {
2537           int src1_x = DXSIZE,          src1_y = DOOR_GFX_PAGEY1;
2538           int dst1_x = DX,              dst1_y = DY + DYSIZE - i;
2539           int src2_x = 0,               src2_y = DOOR_GFX_PAGEY1 + DYSIZE - i;
2540           int dst2_x = DX,              dst2_y = DY;
2541           int width = DXSIZE, height = i;
2542
2543           SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2544           BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2545                            dst1_x, dst1_y);
2546
2547           SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2548           BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2549                            dst2_x, dst2_y);
2550         }
2551         else if (x <= DXSIZE)   /* ANIM_DEFAULT */
2552         {
2553           int j = (door_1.anim_mode == ANIM_DEFAULT ? (DXSIZE - i) / 3 : 0);
2554
2555           SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2556           BlitBitmapMasked(bitmap, drawto,
2557                            DXSIZE, DOOR_GFX_PAGEY1, i, 77,
2558                            DX + DXSIZE - i, DY + j);
2559           BlitBitmapMasked(bitmap, drawto,
2560                            DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
2561                            DX + DXSIZE - i, DY + 140 + j);
2562           SetClipOrigin(bitmap, gc, DX - DXSIZE + i,
2563                         DY - (DOOR_GFX_PAGEY1 + j));
2564           BlitBitmapMasked(bitmap, drawto,
2565                            DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
2566                            DX, DY);
2567           BlitBitmapMasked(bitmap, drawto,
2568                            DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
2569                            DX, DY + 140 - j);
2570
2571           BlitBitmapMasked(bitmap, drawto,
2572                            DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2573                            DX, DY + 77 - j);
2574           BlitBitmapMasked(bitmap, drawto,
2575                            DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2576                            DX, DY + 203 - j);
2577           SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2578           BlitBitmapMasked(bitmap, drawto,
2579                            DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2580                            DX + DXSIZE - i, DY + 77 + j);
2581           BlitBitmapMasked(bitmap, drawto,
2582                            DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2583                            DX + DXSIZE - i, DY + 203 + j);
2584         }
2585
2586         redraw_mask |= REDRAW_DOOR_1;
2587         door_1_done = (a == end);
2588       }
2589
2590       if (door_state & DOOR_ACTION_2)
2591       {
2592         int a = MIN(x * door_2.step_offset, VXSIZE);
2593         int i = (door_state & DOOR_OPEN_2 ? VXSIZE - a : a);
2594
2595         if (x <= VYSIZE)
2596         {
2597           BlitBitmap(bitmap_db_door, drawto,
2598                      DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i / 2,
2599                      VXSIZE, VYSIZE - i / 2, VX, VY);
2600
2601           ClearRectangle(drawto, VX, VY + VYSIZE - i / 2, VXSIZE, i / 2);
2602         }
2603
2604         if (door_2.anim_mode == ANIM_HORIZONTAL && x <= VXSIZE)
2605         {
2606           int src1_x = VXSIZE,          src1_y = DOOR_GFX_PAGEY2;
2607           int dst1_x = VX + VXSIZE - i, dst1_y = VY;
2608           int src2_x = VXSIZE - i,      src2_y = DOOR_GFX_PAGEY2;
2609           int dst2_x = VX,              dst2_y = VY;
2610           int width = i, height = VYSIZE;
2611
2612           SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2613           BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2614                            dst1_x, dst1_y);
2615
2616           SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2617           BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2618                            dst2_x, dst2_y);
2619         }
2620         else if (door_2.anim_mode == ANIM_VERTICAL && x <= VYSIZE)
2621         {
2622           int src1_x = VXSIZE,          src1_y = DOOR_GFX_PAGEY2;
2623           int dst1_x = VX,              dst1_y = VY + VYSIZE - i;
2624           int src2_x = 0,               src2_y = DOOR_GFX_PAGEY2 + VYSIZE - i;
2625           int dst2_x = VX,              dst2_y = VY;
2626           int width = VXSIZE, height = i;
2627
2628           SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2629           BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2630                            dst1_x, dst1_y);
2631
2632           SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2633           BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2634                            dst2_x, dst2_y);
2635         }
2636         else if (x <= VXSIZE)   /* ANIM_DEFAULT */
2637         {
2638           int j = (door_2.anim_mode == ANIM_DEFAULT ? (VXSIZE - i) / 3 : 0);
2639
2640           SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2641           BlitBitmapMasked(bitmap, drawto,
2642                            VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
2643                            VX + VXSIZE - i, VY + j);
2644           SetClipOrigin(bitmap, gc,
2645                         VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2646           BlitBitmapMasked(bitmap, drawto,
2647                            VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
2648                            VX, VY);
2649
2650           BlitBitmapMasked(bitmap, drawto,
2651                            VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2652                            i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
2653           SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2654           BlitBitmapMasked(bitmap, drawto,
2655                            VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2656                            i, VYSIZE / 2 - j,
2657                            VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2658         }
2659
2660         redraw_mask |= REDRAW_DOOR_2;
2661         door_2_done = (a == VXSIZE);
2662       }
2663
2664       BackToFront();
2665
2666       if (game_status == GAME_MODE_MAIN)
2667         DoAnimation();
2668
2669       if (!(door_state & DOOR_NO_DELAY))
2670         WaitUntilDelayReached(&door_delay, door_delay_value);
2671     }
2672   }
2673
2674 #if 0
2675   if (setup.quick_doors)
2676   {
2677     StopSound(SND_DOOR_OPENING);
2678     StopSound(SND_DOOR_CLOSING);
2679   }
2680 #endif
2681
2682   if (door_state & DOOR_ACTION_1)
2683     door1 = door_state & DOOR_ACTION_1;
2684   if (door_state & DOOR_ACTION_2)
2685     door2 = door_state & DOOR_ACTION_2;
2686
2687   return (door1 | door2);
2688 }
2689
2690 void DrawSpecialEditorDoor()
2691 {
2692   /* draw bigger toolbox window */
2693   BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
2694              DOOR_GFX_PAGEX7, 0, EXSIZE + 8, 8,
2695              EX - 4, EY - 12);
2696   BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2697              EX - 4, VY - 4, EXSIZE + 8, EYSIZE - VYSIZE + 4,
2698              EX - 4, EY - 4);
2699
2700   redraw_mask |= REDRAW_ALL;
2701 }
2702
2703 void UndrawSpecialEditorDoor()
2704 {
2705   /* draw normal tape recorder window */
2706   BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2707              EX - 4, EY - 12, EXSIZE + 8, EYSIZE - VYSIZE + 12,
2708              EX - 4, EY - 12);
2709
2710   redraw_mask |= REDRAW_ALL;
2711 }
2712
2713
2714 /* ---------- new tool button stuff ---------------------------------------- */
2715
2716 /* graphic position values for tool buttons */
2717 #define TOOL_BUTTON_YES_XPOS            2
2718 #define TOOL_BUTTON_YES_YPOS            250
2719 #define TOOL_BUTTON_YES_GFX_YPOS        0
2720 #define TOOL_BUTTON_YES_XSIZE           46
2721 #define TOOL_BUTTON_YES_YSIZE           28
2722 #define TOOL_BUTTON_NO_XPOS             52
2723 #define TOOL_BUTTON_NO_YPOS             TOOL_BUTTON_YES_YPOS
2724 #define TOOL_BUTTON_NO_GFX_YPOS         TOOL_BUTTON_YES_GFX_YPOS
2725 #define TOOL_BUTTON_NO_XSIZE            TOOL_BUTTON_YES_XSIZE
2726 #define TOOL_BUTTON_NO_YSIZE            TOOL_BUTTON_YES_YSIZE
2727 #define TOOL_BUTTON_CONFIRM_XPOS        TOOL_BUTTON_YES_XPOS
2728 #define TOOL_BUTTON_CONFIRM_YPOS        TOOL_BUTTON_YES_YPOS
2729 #define TOOL_BUTTON_CONFIRM_GFX_YPOS    30
2730 #define TOOL_BUTTON_CONFIRM_XSIZE       96
2731 #define TOOL_BUTTON_CONFIRM_YSIZE       TOOL_BUTTON_YES_YSIZE
2732 #define TOOL_BUTTON_PLAYER_XSIZE        30
2733 #define TOOL_BUTTON_PLAYER_YSIZE        30
2734 #define TOOL_BUTTON_PLAYER_GFX_XPOS     5
2735 #define TOOL_BUTTON_PLAYER_GFX_YPOS     185
2736 #define TOOL_BUTTON_PLAYER_XPOS         (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2737 #define TOOL_BUTTON_PLAYER_YPOS         (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2738 #define TOOL_BUTTON_PLAYER1_XPOS        (TOOL_BUTTON_PLAYER_XPOS \
2739                                          + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2740 #define TOOL_BUTTON_PLAYER2_XPOS        (TOOL_BUTTON_PLAYER_XPOS \
2741                                          + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2742 #define TOOL_BUTTON_PLAYER3_XPOS        (TOOL_BUTTON_PLAYER_XPOS \
2743                                          + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2744 #define TOOL_BUTTON_PLAYER4_XPOS        (TOOL_BUTTON_PLAYER_XPOS \
2745                                          + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2746 #define TOOL_BUTTON_PLAYER1_YPOS        (TOOL_BUTTON_PLAYER_YPOS \
2747                                          + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2748 #define TOOL_BUTTON_PLAYER2_YPOS        (TOOL_BUTTON_PLAYER_YPOS \
2749                                          + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2750 #define TOOL_BUTTON_PLAYER3_YPOS        (TOOL_BUTTON_PLAYER_YPOS \
2751                                          + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2752 #define TOOL_BUTTON_PLAYER4_YPOS        (TOOL_BUTTON_PLAYER_YPOS \
2753                                          + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2754
2755 static struct
2756 {
2757   int xpos, ypos;
2758   int x, y;
2759   int width, height;
2760   int gadget_id;
2761   char *infotext;
2762 } toolbutton_info[NUM_TOOL_BUTTONS] =
2763 {
2764   {
2765     TOOL_BUTTON_YES_XPOS,       TOOL_BUTTON_YES_GFX_YPOS,
2766     TOOL_BUTTON_YES_XPOS,       TOOL_BUTTON_YES_YPOS,
2767     TOOL_BUTTON_YES_XSIZE,      TOOL_BUTTON_YES_YSIZE,
2768     TOOL_CTRL_ID_YES,
2769     "yes"
2770   },
2771   {
2772     TOOL_BUTTON_NO_XPOS,        TOOL_BUTTON_NO_GFX_YPOS,
2773     TOOL_BUTTON_NO_XPOS,        TOOL_BUTTON_NO_YPOS,
2774     TOOL_BUTTON_NO_XSIZE,       TOOL_BUTTON_NO_YSIZE,
2775     TOOL_CTRL_ID_NO,
2776     "no"
2777   },
2778   {
2779     TOOL_BUTTON_CONFIRM_XPOS,   TOOL_BUTTON_CONFIRM_GFX_YPOS,
2780     TOOL_BUTTON_CONFIRM_XPOS,   TOOL_BUTTON_CONFIRM_YPOS,
2781     TOOL_BUTTON_CONFIRM_XSIZE,  TOOL_BUTTON_CONFIRM_YSIZE,
2782     TOOL_CTRL_ID_CONFIRM,
2783     "confirm"
2784   },
2785   {
2786     TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2787     TOOL_BUTTON_PLAYER1_XPOS,   TOOL_BUTTON_PLAYER1_YPOS,
2788     TOOL_BUTTON_PLAYER_XSIZE,   TOOL_BUTTON_PLAYER_YSIZE,
2789     TOOL_CTRL_ID_PLAYER_1,
2790     "player 1"
2791   },
2792   {
2793     TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2794     TOOL_BUTTON_PLAYER2_XPOS,   TOOL_BUTTON_PLAYER2_YPOS,
2795     TOOL_BUTTON_PLAYER_XSIZE,   TOOL_BUTTON_PLAYER_YSIZE,
2796     TOOL_CTRL_ID_PLAYER_2,
2797     "player 2"
2798   },
2799   {
2800     TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2801     TOOL_BUTTON_PLAYER3_XPOS,   TOOL_BUTTON_PLAYER3_YPOS,
2802     TOOL_BUTTON_PLAYER_XSIZE,   TOOL_BUTTON_PLAYER_YSIZE,
2803     TOOL_CTRL_ID_PLAYER_3,
2804     "player 3"
2805   },
2806   {
2807     TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2808     TOOL_BUTTON_PLAYER4_XPOS,   TOOL_BUTTON_PLAYER4_YPOS,
2809     TOOL_BUTTON_PLAYER_XSIZE,   TOOL_BUTTON_PLAYER_YSIZE,
2810     TOOL_CTRL_ID_PLAYER_4,
2811     "player 4"
2812   }
2813 };
2814
2815 void CreateToolButtons()
2816 {
2817   int i;
2818
2819   for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2820   {
2821     Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2822     Bitmap *deco_bitmap = None;
2823     int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2824     struct GadgetInfo *gi;
2825     unsigned long event_mask;
2826     int gd_xoffset, gd_yoffset;
2827     int gd_x1, gd_x2, gd_y;
2828     int id = i;
2829
2830     event_mask = GD_EVENT_RELEASED;
2831
2832     gd_xoffset = toolbutton_info[i].xpos;
2833     gd_yoffset = toolbutton_info[i].ypos;
2834     gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2835     gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2836     gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2837
2838     if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2839     {
2840       int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
2841
2842       getMiniGraphicSource(PLAYER_NR_GFX(IMG_PLAYER_1, player_nr),
2843                            &deco_bitmap, &deco_x, &deco_y);
2844       deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2845       deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2846     }
2847
2848     gi = CreateGadget(GDI_CUSTOM_ID, id,
2849                       GDI_INFO_TEXT, toolbutton_info[i].infotext,
2850                       GDI_X, DX + toolbutton_info[i].x,
2851                       GDI_Y, DY + toolbutton_info[i].y,
2852                       GDI_WIDTH, toolbutton_info[i].width,
2853                       GDI_HEIGHT, toolbutton_info[i].height,
2854                       GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2855                       GDI_STATE, GD_BUTTON_UNPRESSED,
2856                       GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
2857                       GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
2858                       GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
2859                       GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2860                       GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2861                       GDI_DECORATION_SHIFTING, 1, 1,
2862                       GDI_EVENT_MASK, event_mask,
2863                       GDI_CALLBACK_ACTION, HandleToolButtons,
2864                       GDI_END);
2865
2866     if (gi == NULL)
2867       Error(ERR_EXIT, "cannot create gadget");
2868
2869     tool_gadget[id] = gi;
2870   }
2871 }
2872
2873 void FreeToolButtons()
2874 {
2875   int i;
2876
2877   for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2878     FreeGadget(tool_gadget[i]);
2879 }
2880
2881 static void UnmapToolButtons()
2882 {
2883   int i;
2884
2885   for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2886     UnmapGadget(tool_gadget[i]);
2887 }
2888
2889 static void HandleToolButtons(struct GadgetInfo *gi)
2890 {
2891   request_gadget_id = gi->custom_id;
2892 }
2893
2894 #if 1
2895
2896 static struct
2897 {
2898   int element_em;
2899   boolean is_rnd_to_em_mapping;
2900
2901   int element_rnd;
2902   int action;
2903   int direction;
2904 }
2905 mapping_EM_to_RND_list[] =
2906 {
2907   {
2908     Xblank,                             TRUE,
2909     EL_EMPTY,                           -1, -1
2910   },
2911   {
2912     Yacid_splash_eB,                    FALSE,
2913     EL_EMPTY,                           -1, -1
2914   },
2915   {
2916     Yacid_splash_wB,                    FALSE,
2917     EL_EMPTY,                           -1, -1
2918   },
2919
2920 #ifdef EM_ENGINE_BAD_ROLL
2921   {
2922     Xstone_force_e,                     FALSE,
2923     EL_ROCK,                            ACTION_MOVING, MV_BIT_RIGHT
2924   },
2925   {
2926     Xstone_force_w,                     FALSE,
2927     EL_ROCK,                            ACTION_MOVING, MV_BIT_LEFT
2928   },
2929   {
2930     Xnut_force_e,                       FALSE,
2931     EL_NUT,                             ACTION_MOVING, MV_BIT_RIGHT
2932   },
2933   {
2934     Xnut_force_w,                       FALSE,
2935     EL_NUT,                             ACTION_MOVING, MV_BIT_LEFT
2936   },
2937   {
2938     Xspring_force_e,                    FALSE,
2939     EL_SPRING,                          ACTION_MOVING, MV_BIT_RIGHT
2940   },
2941   {
2942     Xspring_force_w,                    FALSE,
2943     EL_SPRING,                          ACTION_MOVING, MV_BIT_LEFT
2944   },
2945   {
2946     Xemerald_force_e,                   FALSE,
2947     EL_EMERALD,                         ACTION_MOVING, MV_BIT_RIGHT
2948   },
2949   {
2950     Xemerald_force_w,                   FALSE,
2951     EL_EMERALD,                         ACTION_MOVING, MV_BIT_LEFT
2952   },
2953   {
2954     Xdiamond_force_e,                   FALSE,
2955     EL_DIAMOND,                         ACTION_MOVING, MV_BIT_RIGHT
2956   },
2957   {
2958     Xdiamond_force_w,                   FALSE,
2959     EL_DIAMOND,                         ACTION_MOVING, MV_BIT_LEFT
2960   },
2961   {
2962     Xbomb_force_e,                      FALSE,
2963     EL_BOMB,                            ACTION_MOVING, MV_BIT_RIGHT
2964   },
2965   {
2966     Xbomb_force_w,                      FALSE,
2967     EL_BOMB,                            ACTION_MOVING, MV_BIT_LEFT
2968   },
2969 #endif
2970
2971   {
2972     Xstone,                             TRUE,
2973     EL_ROCK,                            -1, -1
2974   },
2975   {
2976     Xstone_pause,                       FALSE,
2977     EL_ROCK,                            -1, -1
2978   },
2979   {
2980     Xstone_fall,                        FALSE,
2981     EL_ROCK,                            ACTION_FALLING, -1
2982   },
2983   {
2984     Ystone_s,                           FALSE,
2985     EL_ROCK,                            ACTION_FALLING, -1
2986   },
2987   {
2988     Ystone_sB,                          FALSE,
2989     EL_ROCK,                            ACTION_FALLING, -1
2990   },
2991   {
2992     Ystone_e,                           FALSE,
2993     EL_ROCK,                            ACTION_MOVING, MV_BIT_RIGHT
2994   },
2995   {
2996     Ystone_eB,                          FALSE,
2997     EL_ROCK,                            ACTION_MOVING, MV_BIT_RIGHT
2998   },
2999   {
3000     Ystone_w,                           FALSE,
3001     EL_ROCK,                            ACTION_MOVING, MV_BIT_LEFT
3002   },
3003   {
3004     Ystone_wB,                          FALSE,
3005     EL_ROCK,                            ACTION_MOVING, MV_BIT_LEFT
3006   },
3007   {
3008     Xnut,                               TRUE,
3009     EL_NUT,                             -1, -1
3010   },
3011   {
3012     Xnut_pause,                         FALSE,
3013     EL_NUT,                             -1, -1
3014   },
3015   {
3016     Xnut_fall,                          FALSE,
3017     EL_NUT,                             ACTION_FALLING, -1
3018   },
3019   {
3020     Ynut_s,                             FALSE,
3021     EL_NUT,                             ACTION_FALLING, -1
3022   },
3023   {
3024     Ynut_sB,                            FALSE,
3025     EL_NUT,                             ACTION_FALLING, -1
3026   },
3027   {
3028     Ynut_e,                             FALSE,
3029     EL_NUT,                             ACTION_MOVING, MV_BIT_RIGHT
3030   },
3031   {
3032     Ynut_eB,                            FALSE,
3033     EL_NUT,                             ACTION_MOVING, MV_BIT_RIGHT
3034   },
3035   {
3036     Ynut_w,                             FALSE,
3037     EL_NUT,                             ACTION_MOVING, MV_BIT_LEFT
3038   },
3039   {
3040     Ynut_wB,                            FALSE,
3041     EL_NUT,                             ACTION_MOVING, MV_BIT_LEFT
3042   },
3043   {
3044     Xbug_n,                             TRUE,
3045     EL_BUG_UP,                          ACTION_MOVING, MV_BIT_UP
3046   },
3047   {
3048     Xbug_e,                             TRUE,
3049     EL_BUG_RIGHT,                       ACTION_MOVING, MV_BIT_RIGHT
3050   },
3051   {
3052     Xbug_s,                             TRUE,
3053     EL_BUG_DOWN,                        ACTION_MOVING, MV_BIT_DOWN
3054   },
3055   {
3056     Xbug_w,                             TRUE,
3057     EL_BUG_LEFT,                        ACTION_MOVING, MV_BIT_LEFT
3058   },
3059   {
3060     Xbug_gon,                           FALSE,
3061     EL_BUG_UP,                          ACTION_MOVING, MV_BIT_UP
3062   },
3063   {
3064     Xbug_goe,                           FALSE,
3065     EL_BUG_RIGHT,                       ACTION_MOVING, MV_BIT_RIGHT
3066   },
3067   {
3068     Xbug_gos,                           FALSE,
3069     EL_BUG_DOWN,                        ACTION_MOVING, MV_BIT_DOWN
3070   },
3071   {
3072     Xbug_gow,                           FALSE,
3073     EL_BUG_LEFT,                        ACTION_MOVING, MV_BIT_LEFT
3074   },
3075   {
3076     Ybug_n,                             FALSE,
3077     EL_BUG_UP,                          ACTION_MOVING, MV_BIT_UP
3078   },
3079   {
3080     Ybug_nB,                            FALSE,
3081     EL_BUG_UP,                          ACTION_MOVING, MV_BIT_UP
3082   },
3083   {
3084     Ybug_e,                             FALSE,
3085     EL_BUG_RIGHT,                       ACTION_MOVING, MV_BIT_RIGHT
3086   },
3087   {
3088     Ybug_eB,                            FALSE,
3089     EL_BUG_RIGHT,                       ACTION_MOVING, MV_BIT_RIGHT
3090   },
3091   {
3092     Ybug_s,                             FALSE,
3093     EL_BUG_DOWN,                        ACTION_MOVING, MV_BIT_DOWN
3094   },
3095   {
3096     Ybug_sB,                            FALSE,
3097     EL_BUG_DOWN,                        ACTION_MOVING, MV_BIT_DOWN
3098   },
3099   {
3100     Ybug_w,                             FALSE,
3101     EL_BUG_LEFT,                        ACTION_MOVING, MV_BIT_LEFT
3102   },
3103   {
3104     Ybug_wB,                            FALSE,
3105     EL_BUG_LEFT,                        ACTION_MOVING, MV_BIT_LEFT
3106   },
3107   {
3108     Ybug_w_n,                           FALSE,
3109     EL_BUG_UP,                          ACTION_TURNING_FROM_LEFT, MV_BIT_UP
3110   },
3111   {
3112     Ybug_n_e,                           FALSE,
3113     EL_BUG_RIGHT,                       ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3114   },
3115   {
3116     Ybug_e_s,                           FALSE,
3117     EL_BUG_DOWN,                        ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
3118   },
3119   {
3120     Ybug_s_w,                           FALSE,
3121     EL_BUG_LEFT,                        ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3122   },
3123   {
3124     Ybug_e_n,                           FALSE,
3125     EL_BUG_UP,                          ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
3126   },
3127   {
3128     Ybug_s_e,                           FALSE,
3129     EL_BUG_RIGHT,                       ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3130   },
3131   {
3132     Ybug_w_s,                           FALSE,
3133     EL_BUG_DOWN,                        ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
3134   },
3135   {
3136     Ybug_n_w,                           FALSE,
3137     EL_BUG_LEFT,                        ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3138   },
3139   {
3140     Ybug_stone,                         FALSE,
3141     EL_ROCK,                            -1, -1
3142   },
3143   {
3144     Ybug_spring,                        FALSE,
3145     EL_SPRING,                          -1, -1
3146   },
3147   {
3148     Xtank_n,                            TRUE,
3149     EL_SPACESHIP_UP,                    ACTION_MOVING, MV_BIT_UP
3150   },
3151   {
3152     Xtank_e,                            TRUE,
3153     EL_SPACESHIP_RIGHT,                 ACTION_MOVING, MV_BIT_RIGHT
3154   },
3155   {
3156     Xtank_s,                            TRUE,
3157     EL_SPACESHIP_DOWN,                  ACTION_MOVING, MV_BIT_DOWN
3158   },
3159   {
3160     Xtank_w,                            TRUE,
3161     EL_SPACESHIP_LEFT,                  ACTION_MOVING, MV_BIT_LEFT
3162   },
3163   {
3164     Xtank_gon,                          FALSE,
3165     EL_SPACESHIP_UP,                    ACTION_MOVING, MV_BIT_UP
3166   },
3167   {
3168     Xtank_goe,                          FALSE,
3169     EL_SPACESHIP_RIGHT,                 ACTION_MOVING, MV_BIT_RIGHT
3170   },
3171   {
3172     Xtank_gos,                          FALSE,
3173     EL_SPACESHIP_DOWN,                  ACTION_MOVING, MV_BIT_DOWN
3174   },
3175   {
3176     Xtank_gow,                          FALSE,
3177     EL_SPACESHIP_LEFT,                  ACTION_MOVING, MV_BIT_LEFT
3178   },
3179   {
3180     Ytank_n,                            FALSE,
3181     EL_SPACESHIP_UP,                    ACTION_MOVING, MV_BIT_UP
3182   },
3183   {
3184     Ytank_nB,                           FALSE,
3185     EL_SPACESHIP_UP,                    ACTION_MOVING, MV_BIT_UP
3186   },
3187   {
3188     Ytank_e,                            FALSE,
3189     EL_SPACESHIP_RIGHT,                 ACTION_MOVING, MV_BIT_RIGHT
3190   },
3191   {
3192     Ytank_eB,                           FALSE,
3193     EL_SPACESHIP_RIGHT,                 ACTION_MOVING, MV_BIT_RIGHT
3194   },
3195   {
3196     Ytank_s,                            FALSE,
3197     EL_SPACESHIP_DOWN,                  ACTION_MOVING, MV_BIT_DOWN
3198   },
3199   {
3200     Ytank_sB,                           FALSE,
3201     EL_SPACESHIP_DOWN,                  ACTION_MOVING, MV_BIT_DOWN
3202   },
3203   {
3204     Ytank_w,                            FALSE,
3205     EL_SPACESHIP_LEFT,                  ACTION_MOVING, MV_BIT_LEFT
3206   },
3207   {
3208     Ytank_wB,                           FALSE,
3209     EL_SPACESHIP_LEFT,                  ACTION_MOVING, MV_BIT_LEFT
3210   },
3211   {
3212     Ytank_w_n,                          FALSE,
3213     EL_SPACESHIP_UP,                    ACTION_TURNING_FROM_LEFT, MV_BIT_UP
3214   },
3215   {
3216     Ytank_n_e,                          FALSE,
3217     EL_SPACESHIP_RIGHT,                 ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3218   },
3219   {
3220     Ytank_e_s,                          FALSE,
3221     EL_SPACESHIP_DOWN,                  ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
3222   },
3223   {
3224     Ytank_s_w,                          FALSE,
3225     EL_SPACESHIP_LEFT,                  ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3226   },
3227   {
3228     Ytank_e_n,                          FALSE,
3229     EL_SPACESHIP_UP,                    ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
3230   },
3231   {
3232     Ytank_s_e,                          FALSE,
3233     EL_SPACESHIP_RIGHT,                 ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3234   },
3235   {
3236     Ytank_w_s,                          FALSE,
3237     EL_SPACESHIP_DOWN,                  ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
3238   },
3239   {
3240     Ytank_n_w,                          FALSE,
3241     EL_SPACESHIP_LEFT,                  ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3242   },
3243   {
3244     Ytank_stone,                        FALSE,
3245     EL_ROCK,                            -1, -1
3246   },
3247   {
3248     Ytank_spring,                       FALSE,
3249     EL_SPRING,                          -1, -1
3250   },
3251   {
3252     Xandroid,                           TRUE,
3253     EL_EMC_ANDROID,                     -1, -1
3254   },
3255   {
3256     Xandroid_1_n,                       TRUE,
3257     EL_EMC_ANDROID_UP,                  ACTION_MOVING, MV_BIT_UP
3258   },
3259   {
3260     Xandroid_2_n,                       FALSE,
3261     EL_EMC_ANDROID_UP,                  ACTION_MOVING, MV_BIT_UP
3262   },
3263   {
3264     Xandroid_1_e,                       TRUE,
3265     EL_EMC_ANDROID_RIGHT,               ACTION_MOVING, MV_BIT_RIGHT
3266   },
3267   {
3268     Xandroid_2_e,                       FALSE,
3269     EL_EMC_ANDROID_RIGHT,               ACTION_MOVING, MV_BIT_RIGHT
3270   },
3271   {
3272     Xandroid_1_w,                       TRUE,
3273     EL_EMC_ANDROID_LEFT,                ACTION_MOVING, MV_BIT_LEFT
3274   },
3275   {
3276     Xandroid_2_w,                       FALSE,
3277     EL_EMC_ANDROID_LEFT,                ACTION_MOVING, MV_BIT_LEFT
3278   },
3279   {
3280     Xandroid_1_s,                       TRUE,
3281     EL_EMC_ANDROID_DOWN,                ACTION_MOVING, MV_BIT_DOWN
3282   },
3283   {
3284     Xandroid_2_s,                       FALSE,
3285     EL_EMC_ANDROID_DOWN,                ACTION_MOVING, MV_BIT_DOWN
3286   },
3287   {
3288     Yandroid_n,                         FALSE,
3289     EL_EMC_ANDROID_UP,                  ACTION_MOVING, MV_BIT_UP
3290   },
3291   {
3292     Yandroid_nB,                        FALSE,
3293     EL_EMC_ANDROID_UP,                  ACTION_MOVING, MV_BIT_UP
3294   },
3295   {
3296     Yandroid_ne,                        FALSE,
3297     EL_EMC_ANDROID_RIGHT_UP,    
3298   },
3299   {
3300     Yandroid_neB,                       FALSE,
3301     EL_EMC_ANDROID_RIGHT_UP,            -1, -1
3302   },
3303   {
3304     Yandroid_e,                         FALSE,
3305     EL_EMC_ANDROID_RIGHT,               ACTION_MOVING, MV_BIT_RIGHT
3306   },
3307   {
3308     Yandroid_eB,                        FALSE,
3309     EL_EMC_ANDROID_RIGHT,               ACTION_MOVING, MV_BIT_RIGHT
3310   },
3311   {
3312     Yandroid_se,                        FALSE,
3313     EL_EMC_ANDROID_RIGHT_DOWN,          -1, -1
3314   },
3315   {
3316     Yandroid_seB,                       FALSE,
3317     EL_EMC_ANDROID_RIGHT_DOWN,          -1, -1
3318   },
3319   {
3320     Yandroid_s,                         FALSE,
3321     EL_EMC_ANDROID_DOWN,                ACTION_MOVING, MV_BIT_DOWN
3322   },
3323   {
3324     Yandroid_sB,                        FALSE,
3325     EL_EMC_ANDROID_DOWN,                ACTION_MOVING, MV_BIT_DOWN
3326   },
3327   {
3328     Yandroid_sw,                        FALSE,
3329     EL_EMC_ANDROID_LEFT_DOWN,           -1, -1
3330   },
3331   {
3332     Yandroid_swB,                       FALSE,
3333     EL_EMC_ANDROID_LEFT_DOWN,           -1, -1
3334   },
3335   {
3336     Yandroid_w,                         FALSE,
3337     EL_EMC_ANDROID_LEFT,                ACTION_MOVING, MV_BIT_LEFT
3338   },
3339   {
3340     Yandroid_wB,                        FALSE,
3341     EL_EMC_ANDROID_LEFT,                ACTION_MOVING, MV_BIT_LEFT
3342   },
3343   {
3344     Yandroid_nw,                        FALSE,
3345     EL_EMC_ANDROID_LEFT_UP,             -1, -1
3346   },
3347   {
3348     Yandroid_nwB,                       FALSE,
3349     EL_EMC_ANDROID_LEFT_UP,             -1, -1
3350   },
3351   {
3352     Xspring,                            TRUE,
3353     EL_SPRING,                          -1, -1
3354   },
3355   {
3356     Xspring_pause,                      FALSE,
3357     EL_SPRING,                          -1, -1
3358   },
3359   {
3360     Xspring_e,                          FALSE,
3361     EL_SPRING,                          ACTION_MOVING, MV_BIT_RIGHT
3362   },
3363   {
3364     Xspring_w,                          FALSE,
3365     EL_SPRING,                          ACTION_MOVING, MV_BIT_LEFT
3366   },
3367   {
3368     Xspring_fall,                       FALSE,
3369     EL_SPRING,                          ACTION_FALLING, -1
3370   },
3371   {
3372     Yspring_s,                          FALSE,
3373     EL_SPRING,                          ACTION_FALLING, -1
3374   },
3375   {
3376     Yspring_sB,                         FALSE,
3377     EL_SPRING,                          ACTION_FALLING, -1
3378   },
3379   {
3380     Yspring_e,                          FALSE,
3381     EL_SPRING,                          ACTION_MOVING, MV_BIT_RIGHT
3382   },
3383   {
3384     Yspring_eB,                         FALSE,
3385     EL_SPRING,                          ACTION_MOVING, MV_BIT_RIGHT
3386   },
3387   {
3388     Yspring_w,                          FALSE,
3389     EL_SPRING,                          ACTION_MOVING, MV_BIT_LEFT
3390   },
3391   {
3392     Yspring_wB,                         FALSE,
3393     EL_SPRING,                          ACTION_MOVING, MV_BIT_LEFT
3394   },
3395   {
3396     Yspring_kill_e,                     FALSE,
3397     EL_SPRING,                          -1, -1
3398   },
3399   {
3400     Yspring_kill_eB,                    FALSE,
3401     EL_SPRING,                          -1, -1
3402   },
3403   {
3404     Yspring_kill_w,                     FALSE,
3405     EL_SPRING,                          -1, -1
3406   },
3407   {
3408     Yspring_kill_wB,                    FALSE,
3409     EL_SPRING,                          -1, -1
3410   },
3411   {
3412     Xeater_n,                           TRUE,
3413     EL_YAMYAM,                          ACTION_MOVING, MV_BIT_UP
3414   },
3415   {
3416     Xeater_e,                           FALSE,
3417     EL_YAMYAM,                          ACTION_MOVING, MV_BIT_RIGHT
3418   },
3419   {
3420     Xeater_w,                           FALSE,
3421     EL_YAMYAM,                          ACTION_MOVING, MV_BIT_LEFT
3422   },
3423   {
3424     Xeater_s,                           FALSE,
3425     EL_YAMYAM,                          ACTION_MOVING, MV_BIT_DOWN
3426   },
3427   {
3428     Yeater_n,                           FALSE,
3429     EL_YAMYAM,                          ACTION_MOVING, MV_BIT_UP
3430   },
3431   {
3432     Yeater_nB,                          FALSE,
3433     EL_YAMYAM,                          ACTION_MOVING, MV_BIT_UP
3434   },
3435   {
3436     Yeater_e,                           FALSE,
3437     EL_YAMYAM,                          ACTION_MOVING, MV_BIT_RIGHT
3438   },
3439   {
3440     Yeater_eB,                          FALSE,
3441     EL_YAMYAM,                          ACTION_MOVING, MV_BIT_RIGHT
3442   },
3443   {
3444     Yeater_s,                           FALSE,
3445     EL_YAMYAM,                          ACTION_MOVING, MV_BIT_DOWN
3446   },
3447   {
3448     Yeater_sB,                          FALSE,
3449     EL_YAMYAM,                          ACTION_MOVING, MV_BIT_DOWN
3450   },
3451   {
3452     Yeater_w,                           FALSE,
3453     EL_YAMYAM,                          ACTION_MOVING, MV_BIT_LEFT
3454   },
3455   {
3456     Yeater_wB,                          FALSE,
3457     EL_YAMYAM,                          ACTION_MOVING, MV_BIT_LEFT
3458   },
3459   {
3460     Yeater_stone,                       FALSE,
3461     EL_ROCK,                            -1, -1
3462   },
3463   {
3464     Yeater_spring,                      FALSE,
3465     EL_SPRING,                          -1, -1
3466   },
3467   {
3468     Xalien,                             TRUE,
3469     EL_ROBOT,                           -1, -1
3470   },
3471   {
3472     Xalien_pause,                       FALSE,
3473     EL_ROBOT,                           -1, -1
3474   },
3475   {
3476     Yalien_n,                           FALSE,
3477     EL_ROBOT,                           ACTION_MOVING, MV_BIT_UP
3478   },
3479   {
3480     Yalien_nB,                          FALSE,
3481     EL_ROBOT,                           ACTION_MOVING, MV_BIT_UP
3482   },
3483   {
3484     Yalien_e,                           FALSE,
3485     EL_ROBOT,                           ACTION_MOVING, MV_BIT_RIGHT
3486   },
3487   {
3488     Yalien_eB,                          FALSE,
3489     EL_ROBOT,                           ACTION_MOVING, MV_BIT_RIGHT
3490   },
3491   {
3492     Yalien_s,                           FALSE,
3493     EL_ROBOT,                           ACTION_MOVING, MV_BIT_DOWN
3494   },
3495   {
3496     Yalien_sB,                          FALSE,
3497     EL_ROBOT,                           ACTION_MOVING, MV_BIT_DOWN
3498   },
3499   {
3500     Yalien_w,                           FALSE,
3501     EL_ROBOT,                           ACTION_MOVING, MV_BIT_LEFT
3502   },
3503   {
3504     Yalien_wB,                          FALSE,
3505     EL_ROBOT,                           ACTION_MOVING, MV_BIT_LEFT
3506   },
3507   {
3508     Yalien_stone,                       FALSE,
3509     EL_ROCK,                            -1, -1
3510   },
3511   {
3512     Yalien_spring,                      FALSE,
3513     EL_SPRING,                          -1, -1
3514   },
3515   {
3516     Xemerald,                           TRUE,
3517     EL_EMERALD,                         -1, -1
3518   },
3519   {
3520     Xemerald_pause,                     FALSE,
3521     EL_EMERALD,                         -1, -1
3522   },
3523   {
3524     Xemerald_fall,                      FALSE,
3525     EL_EMERALD,                         ACTION_FALLING, -1
3526   },
3527   {
3528     Xemerald_shine,                     FALSE,
3529     EL_EMERALD,                         -1, -1
3530   },
3531   {
3532     Yemerald_s,                         FALSE,
3533     EL_EMERALD,                         ACTION_FALLING, -1
3534   },
3535   {
3536     Yemerald_sB,                        FALSE,
3537     EL_EMERALD,                         ACTION_FALLING, -1
3538   },
3539   {
3540     Yemerald_e,                         FALSE,
3541     EL_EMERALD,                         ACTION_MOVING, MV_BIT_RIGHT
3542   },
3543   {
3544     Yemerald_eB,                        FALSE,
3545     EL_EMERALD,                         ACTION_MOVING, MV_BIT_RIGHT
3546   },
3547   {
3548     Yemerald_w,                         FALSE,
3549     EL_EMERALD,                         ACTION_MOVING, MV_BIT_LEFT
3550   },
3551   {
3552     Yemerald_wB,                        FALSE,
3553     EL_EMERALD,                         ACTION_MOVING, MV_BIT_LEFT
3554   },
3555   {
3556     Yemerald_eat,                       FALSE,
3557     EL_EMERALD,                         -1, -1
3558   },
3559   {
3560     Yemerald_stone,                     FALSE,
3561     EL_ROCK,                            -1, -1
3562   },
3563   {
3564     Xdiamond,                           TRUE,
3565     EL_DIAMOND,                         -1, -1
3566   },
3567   {
3568     Xdiamond_pause,                     FALSE,
3569     EL_DIAMOND,                         -1, -1
3570   },
3571   {
3572     Xdiamond_fall,                      FALSE,
3573     EL_DIAMOND,                         ACTION_FALLING, -1
3574   },
3575   {
3576     Xdiamond_shine,                     FALSE,
3577     EL_DIAMOND,                         -1, -1
3578   },
3579   {
3580     Ydiamond_s,                         FALSE,
3581     EL_DIAMOND,                         ACTION_FALLING, -1
3582   },
3583   {
3584     Ydiamond_sB,                        FALSE,
3585     EL_DIAMOND,                         ACTION_FALLING, -1
3586   },
3587   {
3588     Ydiamond_e,                         FALSE,
3589     EL_DIAMOND,                         ACTION_MOVING, MV_BIT_RIGHT
3590   },
3591   {
3592     Ydiamond_eB,                        FALSE,
3593     EL_DIAMOND,                         ACTION_MOVING, MV_BIT_RIGHT
3594   },
3595   {
3596     Ydiamond_w,                         FALSE,
3597     EL_DIAMOND,                         ACTION_MOVING, MV_BIT_LEFT
3598   },
3599   {
3600     Ydiamond_wB,                        FALSE,
3601     EL_DIAMOND,                         ACTION_MOVING, MV_BIT_LEFT
3602   },
3603   {
3604     Ydiamond_eat,                       FALSE,
3605     EL_DIAMOND,                         -1, -1
3606   },
3607   {
3608     Ydiamond_stone,                     FALSE,
3609     EL_ROCK,                            -1, -1
3610   },
3611   {
3612     Xdrip_fall,                         TRUE,
3613     EL_AMOEBA_DROP,                     ACTION_FALLING, -1
3614   },
3615   {
3616     Xdrip_stretch,                      FALSE,
3617     EL_AMOEBA_DROP,                     -1, -1
3618   },
3619   {
3620     Xdrip_stretchB,                     FALSE,
3621     EL_AMOEBA_DROP,                     -1, -1
3622   },
3623   {
3624     Xdrip_eat,                          FALSE,
3625     EL_AMOEBA_DROP,                     -1, -1
3626   },
3627   {
3628     Ydrip_s1,                           FALSE,
3629     EL_AMOEBA_DROP,                     ACTION_FALLING, -1
3630   },
3631   {
3632     Ydrip_s1B,                          FALSE,
3633     EL_AMOEBA_DROP,                     ACTION_FALLING, -1
3634   },
3635   {
3636     Ydrip_s2,                           FALSE,
3637     EL_AMOEBA_DROP,                     ACTION_FALLING, -1
3638   },
3639   {
3640     Ydrip_s2B,                          FALSE,
3641     EL_AMOEBA_DROP,                     ACTION_FALLING, -1
3642   },
3643   {
3644     Xbomb,                              TRUE,
3645     EL_BOMB,                            -1, -1
3646   },
3647   {
3648     Xbomb_pause,                        FALSE,
3649     EL_BOMB,                            -1, -1
3650   },
3651   {
3652     Xbomb_fall,                         FALSE,
3653     EL_BOMB,                            ACTION_FALLING, -1
3654   },
3655   {
3656     Ybomb_s,                            FALSE,
3657     EL_BOMB,                            ACTION_FALLING, -1
3658   },
3659   {
3660     Ybomb_sB,                           FALSE,
3661     EL_BOMB,                            ACTION_FALLING, -1
3662   },
3663   {
3664     Ybomb_e,                            FALSE,
3665     EL_BOMB,                            ACTION_MOVING, MV_BIT_RIGHT
3666   },
3667   {
3668     Ybomb_eB,                           FALSE,
3669     EL_BOMB,                            ACTION_MOVING, MV_BIT_RIGHT
3670   },
3671   {
3672     Ybomb_w,                            FALSE,
3673     EL_BOMB,                            ACTION_MOVING, MV_BIT_LEFT
3674   },
3675   {
3676     Ybomb_wB,                           FALSE,
3677     EL_BOMB,                            ACTION_MOVING, MV_BIT_LEFT
3678   },
3679   {
3680     Ybomb_eat,                          FALSE,
3681     EL_BOMB,                            -1, -1
3682   },
3683   {
3684     Xballoon,                           TRUE,
3685     EL_BALLOON,                         -1, -1
3686   },
3687   {
3688     Yballoon_n,                         FALSE,
3689     EL_BALLOON,                         ACTION_MOVING, MV_BIT_UP
3690   },
3691   {
3692     Yballoon_nB,                        FALSE,
3693     EL_BALLOON,                         ACTION_MOVING, MV_BIT_UP
3694   },
3695   {
3696     Yballoon_e,                         FALSE,
3697     EL_BALLOON,                         ACTION_MOVING, MV_BIT_RIGHT
3698   },
3699   {
3700     Yballoon_eB,                        FALSE,
3701     EL_BALLOON,                         ACTION_MOVING, MV_BIT_RIGHT
3702   },
3703   {
3704     Yballoon_s,                         FALSE,
3705     EL_BALLOON,                         ACTION_MOVING, MV_BIT_DOWN
3706   },
3707   {
3708     Yballoon_sB,                        FALSE,
3709     EL_BALLOON,                         ACTION_MOVING, MV_BIT_DOWN
3710   },
3711   {
3712     Yballoon_w,                         FALSE,
3713     EL_BALLOON,                         ACTION_MOVING, MV_BIT_LEFT
3714   },
3715   {
3716     Yballoon_wB,                        FALSE,
3717     EL_BALLOON,                         ACTION_MOVING, MV_BIT_LEFT
3718   },
3719   {
3720     Xgrass,                             TRUE,
3721     EL_SAND,                            -1, -1
3722   },
3723   {
3724     Ygrass_nB,                          FALSE,
3725     EL_SAND,                            ACTION_MOVING, MV_BIT_UP
3726   },
3727   {
3728     Ygrass_eB,                          FALSE,
3729     EL_SAND,                            ACTION_MOVING, MV_BIT_RIGHT
3730   },
3731   {
3732     Ygrass_sB,                          FALSE,
3733     EL_SAND,                            ACTION_MOVING, MV_BIT_DOWN
3734   },
3735   {
3736     Ygrass_wB,                          FALSE,
3737     EL_SAND,                            ACTION_MOVING, MV_BIT_LEFT
3738   },
3739   {
3740     Xdirt,                              TRUE,
3741     EL_SAND,                            -1, -1
3742   },
3743   {
3744     Ydirt_nB,                           FALSE,
3745     EL_SAND,                            ACTION_MOVING, MV_BIT_UP
3746   },
3747   {
3748     Ydirt_eB,                           FALSE,
3749     EL_SAND,                            ACTION_MOVING, MV_BIT_RIGHT
3750   },
3751   {
3752     Ydirt_sB,                           FALSE,
3753     EL_SAND,                            ACTION_MOVING, MV_BIT_DOWN
3754   },
3755   {
3756     Ydirt_wB,                           FALSE,
3757     EL_SAND,                            ACTION_MOVING, MV_BIT_LEFT
3758   },
3759   {
3760     Xacid_ne,                           TRUE,
3761     EL_ACID_POOL_TOPRIGHT,              -1, -1
3762   },
3763   {
3764     Xacid_se,                           TRUE,
3765     EL_ACID_POOL_BOTTOMRIGHT,           -1, -1
3766   },
3767   {
3768     Xacid_s,                            TRUE,
3769     EL_ACID_POOL_BOTTOM,                -1, -1
3770   },
3771   {
3772     Xacid_sw,                           TRUE,
3773     EL_ACID_POOL_BOTTOMLEFT,            -1, -1
3774   },
3775   {
3776     Xacid_nw,                           TRUE,
3777     EL_ACID_POOL_TOPLEFT,               -1, -1
3778   },
3779   {
3780     Xacid_1,                            TRUE,
3781     EL_ACID,                            -1, -1
3782   },
3783   {
3784     Xacid_2,                            FALSE,
3785     EL_ACID,                            -1, -1
3786   },
3787   {
3788     Xacid_3,                            FALSE,
3789     EL_ACID,                            -1, -1
3790   },
3791   {
3792     Xacid_4,                            FALSE,
3793     EL_ACID,                            -1, -1
3794   },
3795   {
3796     Xacid_5,                            FALSE,
3797     EL_ACID,                            -1, -1
3798   },
3799   {
3800     Xacid_6,                            FALSE,
3801     EL_ACID,                            -1, -1
3802   },
3803   {
3804     Xacid_7,                            FALSE,
3805     EL_ACID,                            -1, -1
3806   },
3807   {
3808     Xacid_8,                            FALSE,
3809     EL_ACID,                            -1, -1
3810   },
3811   {
3812     Xball_1,                            TRUE,
3813     EL_EMC_GENERATOR_BALL,              -1, -1
3814   },
3815   {
3816     Xball_1B,                           FALSE,
3817     EL_EMC_GENERATOR_BALL,              -1, -1
3818   },
3819   {
3820     Xball_2,                            FALSE,
3821     EL_EMC_GENERATOR_BALL,              -1, -1
3822   },
3823   {
3824     Xball_2B,                           FALSE,
3825     EL_EMC_GENERATOR_BALL,              -1, -1
3826   },
3827   {
3828     Yball_eat,                          FALSE,
3829     EL_EMC_GENERATOR_BALL,              -1, -1
3830   },
3831   {
3832     Xgrow_ns,                           TRUE,
3833     EL_EXPANDABLE_WALL_VERTICAL,        -1, -1
3834   },
3835   {
3836     Ygrow_ns_eat,                       FALSE,
3837     EL_EXPANDABLE_WALL_VERTICAL,        -1, -1
3838   },
3839   {
3840     Xgrow_ew,                           TRUE,
3841     EL_EXPANDABLE_WALL_HORIZONTAL,      -1, -1
3842   },
3843   {
3844     Ygrow_ew_eat,                       FALSE,
3845     EL_EXPANDABLE_WALL_HORIZONTAL,      -1, -1
3846   },
3847   {
3848     Xwonderwall,                        TRUE,
3849     EL_MAGIC_WALL,                      -1, -1
3850   },
3851   {
3852     XwonderwallB,                       FALSE,
3853     EL_MAGIC_WALL,                      -1, -1
3854   },
3855   {
3856     Xamoeba_1,                          TRUE,
3857     EL_AMOEBA_WET,                      -1, -1
3858   },
3859   {
3860     Xamoeba_2,                          FALSE,
3861     EL_AMOEBA_WET,                      -1, -1
3862   },
3863   {
3864     Xamoeba_3,                          FALSE,
3865     EL_AMOEBA_WET,                      -1, -1
3866   },
3867   {
3868     Xamoeba_4,                          FALSE,
3869     EL_AMOEBA_WET,                      -1, -1
3870   },
3871   {
3872     Xamoeba_5,                          FALSE,
3873     EL_AMOEBA_WET,                      -1, -1
3874   },
3875   {
3876     Xamoeba_6,                          FALSE,
3877     EL_AMOEBA_WET,                      -1, -1
3878   },
3879   {
3880     Xamoeba_7,                          FALSE,
3881     EL_AMOEBA_WET,                      -1, -1
3882   },
3883   {
3884     Xamoeba_8,                          FALSE,
3885     EL_AMOEBA_WET,                      -1, -1
3886   },
3887   {
3888     Xdoor_1,                            TRUE,
3889     EL_EM_GATE_1,                       -1, -1
3890   },
3891   {
3892     Xdoor_2,                            TRUE,
3893     EL_EM_GATE_2,                       -1, -1
3894   },
3895   {
3896     Xdoor_3,                            TRUE,
3897     EL_EM_GATE_3,                       -1, -1
3898   },
3899   {
3900     Xdoor_4,                            TRUE,
3901     EL_EM_GATE_4,                       -1, -1
3902   },
3903   {
3904     Xdoor_5,                            TRUE,
3905     EL_EMC_GATE_5,                      -1, -1
3906   },
3907   {
3908     Xdoor_6,                            TRUE,
3909     EL_EMC_GATE_6,                      -1, -1
3910   },
3911   {
3912     Xdoor_7,                            TRUE,
3913     EL_EMC_GATE_7,                      -1, -1
3914   },
3915   {
3916     Xdoor_8,                            TRUE,
3917     EL_EMC_GATE_8,                      -1, -1
3918   },
3919   {
3920     Xkey_1,                             TRUE,
3921     EL_EM_KEY_1,                        -1, -1
3922   },
3923   {
3924     Xkey_2,                             TRUE,
3925     EL_EM_KEY_2,                        -1, -1
3926   },
3927   {
3928     Xkey_3,                             TRUE,
3929     EL_EM_KEY_3,                        -1, -1
3930   },
3931   {
3932     Xkey_4,                             TRUE,
3933     EL_EM_KEY_4,                        -1, -1
3934   },
3935   {
3936     Xkey_5,                             TRUE,
3937     EL_EMC_KEY_5,                       -1, -1
3938   },
3939   {
3940     Xkey_6,                             TRUE,
3941     EL_EMC_KEY_6,                       -1, -1
3942   },
3943   {
3944     Xkey_7,                             TRUE,
3945     EL_EMC_KEY_7,                       -1, -1
3946   },
3947   {
3948     Xkey_8,                             TRUE,
3949     EL_EMC_KEY_8,                       -1, -1
3950   },
3951   {
3952     Xwind_n,                            TRUE,
3953     EL_BALLOON_SWITCH_UP,               -1, -1
3954   },
3955   {
3956     Xwind_e,                            TRUE,
3957     EL_BALLOON_SWITCH_RIGHT,            -1, -1
3958   },
3959   {
3960     Xwind_s,                            TRUE,
3961     EL_BALLOON_SWITCH_DOWN,             -1, -1
3962   },
3963   {
3964     Xwind_w,                            TRUE,
3965     EL_BALLOON_SWITCH_LEFT,             -1, -1
3966   },
3967   {
3968     Xwind_nesw,                         TRUE,
3969     EL_BALLOON_SWITCH_ANY,              -1, -1
3970   },
3971   {
3972     Xwind_stop,                         TRUE,
3973     EL_BALLOON_SWITCH_NONE,             -1, -1
3974   },
3975   {
3976     Xexit,                              TRUE,
3977     EL_EXIT_CLOSED,                     -1, -1
3978   },
3979   {
3980     Xexit_1,                            TRUE,
3981     EL_EXIT_OPEN,                       -1, -1
3982   },
3983   {
3984     Xexit_2,                            FALSE,
3985     EL_EXIT_OPEN,                       -1, -1
3986   },
3987   {
3988     Xexit_3,                            FALSE,
3989     EL_EXIT_OPEN,                       -1, -1
3990   },
3991   {
3992     Xdynamite,                          TRUE,
3993     EL_DYNAMITE,                        -1, -1
3994   },
3995   {
3996     Ydynamite_eat,                      FALSE,
3997     EL_DYNAMITE,                        -1, -1
3998   },
3999   {
4000     Xdynamite_1,                        TRUE,
4001     EL_DYNAMITE_ACTIVE,                 -1, -1
4002   },
4003   {
4004     Xdynamite_2,                        FALSE,
4005     EL_DYNAMITE_ACTIVE,                 -1, -1
4006   },
4007   {
4008     Xdynamite_3,                        FALSE,
4009     EL_DYNAMITE_ACTIVE,                 -1, -1
4010   },
4011   {
4012     Xdynamite_4,                        FALSE,
4013     EL_DYNAMITE_ACTIVE,                 -1, -1
4014   },
4015   {
4016     Xbumper,                            TRUE,
4017     EL_EMC_BUMPER,                      -1, -1
4018   },
4019   {
4020     XbumperB,                           FALSE,
4021     EL_EMC_BUMPER,                      -1, -1
4022   },
4023   {
4024     Xwheel,                             TRUE,
4025     EL_ROBOT_WHEEL,                     -1, -1
4026   },
4027   {
4028     XwheelB,                            FALSE,
4029     EL_ROBOT_WHEEL,                     -1, -1
4030   },
4031   {
4032     Xswitch,                            FALSE,
4033     EL_UNKNOWN,                         -1, -1
4034   },
4035   {
4036     XswitchB,                           FALSE,
4037     EL_UNKNOWN,                         -1, -1
4038   },
4039   {
4040     Xsand,                              TRUE,
4041     EL_QUICKSAND_EMPTY,                 -1, -1
4042   },
4043   {
4044     Xsand_stone,                        TRUE,
4045     EL_QUICKSAND_FULL,                  -1, -1
4046   },
4047   {
4048     Xsand_stonein_1,                    FALSE,
4049     EL_QUICKSAND_FULL,                  -1, -1
4050   },
4051   {
4052     Xsand_stonein_2,                    FALSE,
4053     EL_QUICKSAND_FULL,                  -1, -1
4054   },
4055   {
4056     Xsand_stonein_3,                    FALSE,
4057     EL_QUICKSAND_FULL,                  -1, -1
4058   },
4059   {
4060     Xsand_stonein_4,                    FALSE,
4061     EL_QUICKSAND_FULL,                  -1, -1
4062   },
4063   {
4064     Xsand_stonesand_1,                  FALSE,
4065     EL_QUICKSAND_FULL,                  -1, -1
4066   },
4067   {
4068     Xsand_stonesand_2,                  FALSE,
4069     EL_QUICKSAND_FULL,                  -1, -1
4070   },
4071   {
4072     Xsand_stonesand_3,                  FALSE,
4073     EL_QUICKSAND_FULL,                  -1, -1
4074   },
4075   {
4076     Xsand_stonesand_4,                  FALSE,
4077     EL_QUICKSAND_FULL,                  -1, -1
4078   },
4079   {
4080     Xsand_stoneout_1,                   FALSE,
4081     EL_QUICKSAND_FULL,                  -1, -1
4082   },
4083   {
4084     Xsand_stoneout_2,                   FALSE,
4085     EL_QUICKSAND_FULL,                  -1, -1
4086   },
4087   {
4088     Xsand_sandstone_1,                  FALSE,
4089     EL_QUICKSAND_FULL,                  -1, -1
4090   },
4091   {
4092     Xsand_sandstone_2,                  FALSE,
4093     EL_QUICKSAND_FULL,                  -1, -1
4094   },
4095   {
4096     Xsand_sandstone_3,                  FALSE,
4097     EL_QUICKSAND_FULL,                  -1, -1
4098   },
4099   {
4100     Xsand_sandstone_4,                  FALSE,
4101     EL_QUICKSAND_FULL,                  -1, -1
4102   },
4103   {
4104     Xplant,                             TRUE,
4105     EL_EMC_PLANT,                       -1, -1
4106   },
4107   {
4108     Yplant,                             FALSE,
4109     EL_EMC_PLANT,                       -1, -1
4110   },
4111   {
4112     Xlenses,                            TRUE,
4113     EL_EMC_LENSES,                      -1, -1
4114   },
4115   {
4116     Xmagnify,                           TRUE,
4117     EL_EMC_MAGNIFIER,                   -1, -1
4118   },
4119   {
4120     Xdripper,                           FALSE,
4121     EL_UNKNOWN,                         -1, -1
4122   },
4123   {
4124     XdripperB,                          FALSE,
4125     EL_UNKNOWN,                         -1, -1
4126   },
4127   {
4128     Xfake_blank,                        TRUE,
4129     EL_INVISIBLE_WALL,                  -1, -1
4130   },
4131   {
4132     Xfake_blankB,                       FALSE,
4133     EL_INVISIBLE_WALL,                  -1, -1
4134   },
4135   {
4136     Xfake_grass,                        TRUE,
4137     EL_INVISIBLE_SAND,                  -1, -1
4138   },
4139   {
4140     Xfake_grassB,                       FALSE,
4141     EL_INVISIBLE_SAND,                  -1, -1
4142   },
4143   {
4144     Xfake_door_1,                       TRUE,
4145     EL_EM_GATE_1_GRAY,                  -1, -1
4146   },
4147   {
4148     Xfake_door_2,                       TRUE,
4149     EL_EM_GATE_2_GRAY,                  -1, -1
4150   },
4151   {
4152     Xfake_door_3,                       TRUE,
4153     EL_EM_GATE_3_GRAY,                  -1, -1
4154   },
4155   {
4156     Xfake_door_4,                       TRUE,
4157     EL_EM_GATE_4_GRAY,                  -1, -1
4158   },
4159   {
4160     Xfake_door_5,                       TRUE,
4161     EL_EMC_GATE_5_GRAY,                 -1, -1
4162   },
4163   {
4164     Xfake_door_6,                       TRUE,
4165     EL_EMC_GATE_6_GRAY,                 -1, -1
4166   },
4167   {
4168     Xfake_door_7,                       TRUE,
4169     EL_EMC_GATE_7_GRAY,                 -1, -1
4170   },
4171   {
4172     Xfake_door_8,                       TRUE,
4173     EL_EMC_GATE_8_GRAY,                 -1, -1
4174   },
4175   {
4176     Xsteel_1,                           TRUE,
4177     EL_STEELWALL,                       -1, -1
4178   },
4179   {
4180     Xsteel_2,                           FALSE,
4181     EL_UNKNOWN,                         -1, -1
4182   },
4183   {
4184     Xsteel_3,                           TRUE,
4185     EL_EMC_STEELWALL_1,                 -1, -1
4186   },
4187   {
4188     Xsteel_4,                           FALSE,
4189     EL_UNKNOWN,                         -1, -1
4190   },
4191   {
4192     Xwall_1,                            TRUE,
4193     EL_WALL,                            -1, -1
4194   },
4195   {
4196     Xwall_2,                            FALSE,
4197     EL_UNKNOWN,                         -1, -1
4198   },
4199   {
4200     Xwall_3,                            FALSE,
4201     EL_UNKNOWN,                         -1, -1
4202   },
4203   {
4204     Xwall_4,                            FALSE,
4205     EL_UNKNOWN,                         -1, -1
4206   },
4207   {
4208     Xround_wall_1,                      TRUE,
4209     EL_WALL_SLIPPERY,                   -1, -1
4210   },
4211   {
4212     Xround_wall_2,                      FALSE,
4213     EL_UNKNOWN,                         -1, -1
4214   },
4215   {
4216     Xround_wall_3,                      FALSE,
4217     EL_UNKNOWN,                         -1, -1
4218   },
4219   {
4220     Xround_wall_4,                      FALSE,
4221     EL_UNKNOWN,                         -1, -1
4222   },
4223   {
4224     Xdecor_1,                           FALSE,
4225     EL_UNKNOWN,                         -1, -1
4226   },
4227   {
4228     Xdecor_2,                           TRUE,
4229     EL_EMC_WALL_6,                      -1, -1
4230   },
4231   {
4232     Xdecor_3,                           TRUE,
4233     EL_EMC_WALL_4,                      -1, -1
4234   },
4235   {
4236     Xdecor_4,                           TRUE,
4237     EL_EMC_WALL_5,                      -1, -1
4238   },
4239   {
4240     Xdecor_5,                           TRUE,
4241     EL_EMC_WALL_7,                      -1, -1
4242   },
4243   {
4244     Xdecor_6,                           TRUE,
4245     EL_EMC_WALL_8,                      -1, -1
4246   },
4247   {
4248     Xdecor_7,                           FALSE,
4249     EL_UNKNOWN,                         -1, -1
4250   },
4251   {
4252     Xdecor_8,                           TRUE,
4253     EL_EMC_WALL_1,                      -1, -1
4254   },
4255   {
4256     Xdecor_9,                           TRUE,
4257     EL_EMC_WALL_2,                      -1, -1
4258   },
4259   {
4260     Xdecor_10,                          TRUE,
4261     EL_EMC_WALL_3,                      -1, -1
4262   },
4263   {
4264     Xdecor_11,                          FALSE,
4265     EL_UNKNOWN,                         -1, -1
4266   },
4267   {
4268     Xdecor_12,                          FALSE,
4269     EL_UNKNOWN,                         -1, -1
4270   },
4271   {
4272     Xalpha_0,                           TRUE,
4273     EL_CHAR('0'),                       -1, -1
4274   },
4275   {
4276     Xalpha_1,                           TRUE,
4277     EL_CHAR('1'),                       -1, -1
4278   },
4279   {
4280     Xalpha_2,                           TRUE,
4281     EL_CHAR('2'),                       -1, -1
4282   },
4283   {
4284     Xalpha_3,                           TRUE,
4285     EL_CHAR('3'),                       -1, -1
4286   },
4287   {
4288     Xalpha_4,                           TRUE,
4289     EL_CHAR('4'),                       -1, -1
4290   },
4291   {
4292     Xalpha_5,                           TRUE,
4293     EL_CHAR('5'),                       -1, -1
4294   },
4295   {
4296     Xalpha_6,                           TRUE,
4297     EL_CHAR('6'),                       -1, -1
4298   },
4299   {
4300     Xalpha_7,                           TRUE,
4301     EL_CHAR('7'),                       -1, -1
4302   },
4303   {
4304     Xalpha_8,                           TRUE,
4305     EL_CHAR('8'),                       -1, -1
4306   },
4307   {
4308     Xalpha_9,                           TRUE,
4309     EL_CHAR('9'),                       -1, -1
4310   },
4311   {
4312     Xalpha_excla,                       TRUE,
4313     EL_CHAR('!'),                       -1, -1
4314   },
4315   {
4316     Xalpha_quote,                       TRUE,
4317     EL_CHAR('"'),                       -1, -1
4318   },
4319   {
4320     Xalpha_comma,                       TRUE,
4321     EL_CHAR(','),                       -1, -1
4322   },
4323   {
4324     Xalpha_minus,                       TRUE,
4325     EL_CHAR('-'),                       -1, -1
4326   },
4327   {
4328     Xalpha_perio,                       TRUE,
4329     EL_CHAR('.'),                       -1, -1
4330   },
4331   {
4332     Xalpha_colon,                       TRUE,
4333     EL_CHAR(':'),                       -1, -1
4334   },
4335   {
4336     Xalpha_quest,                       TRUE,
4337     EL_CHAR('?'),                       -1, -1
4338   },
4339   {
4340     Xalpha_a,                           TRUE,
4341     EL_CHAR('A'),                       -1, -1
4342   },
4343   {
4344     Xalpha_b,                           TRUE,
4345     EL_CHAR('B'),                       -1, -1
4346   },
4347   {
4348     Xalpha_c,                           TRUE,
4349     EL_CHAR('C'),                       -1, -1
4350   },
4351   {
4352     Xalpha_d,                           TRUE,
4353     EL_CHAR('D'),                       -1, -1
4354   },
4355   {
4356     Xalpha_e,                           TRUE,
4357     EL_CHAR('E'),                       -1, -1
4358   },
4359   {
4360     Xalpha_f,                           TRUE,
4361     EL_CHAR('F'),                       -1, -1
4362   },
4363   {
4364     Xalpha_g,                           TRUE,
4365     EL_CHAR('G'),                       -1, -1
4366   },
4367   {
4368     Xalpha_h,                           TRUE,
4369     EL_CHAR('H'),                       -1, -1
4370   },
4371   {
4372     Xalpha_i,                           TRUE,
4373     EL_CHAR('I'),                       -1, -1
4374   },
4375   {
4376     Xalpha_j,                           TRUE,
4377     EL_CHAR('J'),                       -1, -1
4378   },
4379   {
4380     Xalpha_k,                           TRUE,
4381     EL_CHAR('K'),                       -1, -1
4382   },
4383   {
4384     Xalpha_l,                           TRUE,
4385     EL_CHAR('L'),                       -1, -1
4386   },
4387   {
4388     Xalpha_m,                           TRUE,
4389     EL_CHAR('M'),                       -1, -1
4390   },
4391   {
4392     Xalpha_n,                           TRUE,
4393     EL_CHAR('N'),                       -1, -1
4394   },
4395   {
4396     Xalpha_o,                           TRUE,
4397     EL_CHAR('O'),                       -1, -1
4398   },
4399   {
4400     Xalpha_p,                           TRUE,
4401     EL_CHAR('P'),                       -1, -1
4402   },
4403   {
4404     Xalpha_q,                           TRUE,
4405     EL_CHAR('Q'),                       -1, -1
4406   },
4407   {
4408     Xalpha_r,                           TRUE,
4409     EL_CHAR('R'),                       -1, -1
4410   },
4411   {
4412     Xalpha_s,                           TRUE,
4413     EL_CHAR('S'),                       -1, -1
4414   },
4415   {
4416     Xalpha_t,                           TRUE,
4417     EL_CHAR('T'),                       -1, -1
4418   },
4419   {
4420     Xalpha_u,                           TRUE,
4421     EL_CHAR('U'),                       -1, -1
4422   },
4423   {
4424     Xalpha_v,                           TRUE,
4425     EL_CHAR('V'),                       -1, -1
4426   },
4427   {
4428     Xalpha_w,                           TRUE,
4429     EL_CHAR('W'),                       -1, -1
4430   },
4431   {
4432     Xalpha_x,                           TRUE,
4433     EL_CHAR('X'),                       -1, -1
4434   },
4435   {
4436     Xalpha_y,                           TRUE,
4437     EL_CHAR('Y'),                       -1, -1
4438   },
4439   {
4440     Xalpha_z,                           TRUE,
4441     EL_CHAR('Z'),                       -1, -1
4442   },
4443   {
4444     Xalpha_arrow_e,                     TRUE,
4445     EL_CHAR('>'),                       -1, -1
4446   },
4447   {
4448     Xalpha_arrow_w,                     TRUE,
4449     EL_CHAR('<'),                       -1, -1
4450   },
4451   {
4452     Xalpha_copyr,                       TRUE,
4453     EL_CHAR('©'),                       -1, -1
4454   },
4455
4456   {
4457     Zplayer,                            TRUE,
4458     EL_PLAYER_1,                        -1, -1
4459   },
4460
4461   {
4462     ZBORDER,                            TRUE,
4463     EL_EMC_LEVEL_BORDER,                -1, -1
4464   },
4465
4466   {
4467     -1,                                 FALSE,
4468     -1,                                 -1, -1
4469   }
4470 };
4471
4472 int map_element_RND_to_EM(int element_rnd)
4473 {
4474   static unsigned short mapping_RND_to_EM[NUM_FILE_ELEMENTS];
4475   static boolean mapping_initialized = FALSE;
4476
4477   if (!mapping_initialized)
4478   {
4479     int i;
4480
4481     /* return "Xalpha_quest" for all undefined elements in mapping array */
4482     for (i = 0; i < NUM_FILE_ELEMENTS; i++)
4483       mapping_RND_to_EM[i] = Xalpha_quest;
4484
4485     for (i = 0; mapping_EM_to_RND_list[i].element_em != -1; i++)
4486       if (mapping_EM_to_RND_list[i].is_rnd_to_em_mapping)
4487         mapping_RND_to_EM[mapping_EM_to_RND_list[i].element_rnd] =
4488           mapping_EM_to_RND_list[i].element_em;
4489
4490     mapping_initialized = TRUE;
4491   }
4492
4493   if (element_rnd >= 0 && element_rnd < NUM_FILE_ELEMENTS)
4494     return mapping_RND_to_EM[element_rnd];
4495
4496   Error(ERR_WARN, "invalid RND level element %d", element_rnd);
4497
4498   return EL_UNKNOWN;
4499 }
4500
4501 int map_element_EM_to_RND(int element_em)
4502 {
4503   static unsigned short mapping_EM_to_RND[TILE_MAX];
4504   static boolean mapping_initialized = FALSE;
4505
4506   if (!mapping_initialized)
4507   {
4508     int i;
4509
4510     /* return "EL_UNKNOWN" for all undefined elements in mapping array */
4511     for (i = 0; i < TILE_MAX; i++)
4512       mapping_EM_to_RND[i] = EL_UNKNOWN;
4513
4514     for (i = 0; mapping_EM_to_RND_list[i].element_em != -1; i++)
4515       mapping_EM_to_RND[mapping_EM_to_RND_list[i].element_em] =
4516         mapping_EM_to_RND_list[i].element_rnd;
4517
4518     mapping_initialized = TRUE;
4519   }
4520
4521   if (element_em >= 0 && element_em < TILE_MAX)
4522     return mapping_EM_to_RND[element_em];
4523
4524   Error(ERR_WARN, "invalid EM level element %d", element_em);
4525
4526   return EL_UNKNOWN;
4527 }
4528
4529 #else
4530
4531 int map_element_RND_to_EM(int element_rnd)
4532 {
4533   static unsigned short mapping_RND_to_EM[NUM_FILE_ELEMENTS];
4534   static boolean mapping_initialized = FALSE;
4535
4536   struct
4537   {
4538     int element_em;
4539     int element_rnd;
4540   }
4541   mapping_RND_to_EM_list[] =
4542   {
4543     { Xblank,                   EL_EMPTY                        },
4544     { Xstone,                   EL_ROCK                         },
4545     { Xnut,                     EL_NUT                          },
4546     { Xbug_n,                   EL_BUG_UP                       },
4547     { Xbug_e,                   EL_BUG_RIGHT                    },
4548     { Xbug_s,                   EL_BUG_DOWN                     },
4549     { Xbug_w,                   EL_BUG_LEFT                     },
4550     { Xtank_n,                  EL_SPACESHIP_UP                 },
4551     { Xtank_e,                  EL_SPACESHIP_RIGHT              },
4552     { Xtank_s,                  EL_SPACESHIP_DOWN               },
4553     { Xtank_w,                  EL_SPACESHIP_LEFT               },
4554     { Xandroid,                 EL_EMC_ANDROID                  },
4555     { Xandroid_1_n,             EL_EMC_ANDROID_UP               },
4556     { Xandroid_1_e,             EL_EMC_ANDROID_RIGHT            },
4557     { Xandroid_1_w,             EL_EMC_ANDROID_LEFT             },
4558     { Xandroid_1_s,             EL_EMC_ANDROID_DOWN             },
4559     { Xspring,                  EL_SPRING                       },
4560     { Xeater_n,                 EL_YAMYAM                       },
4561     { Xalien,                   EL_ROBOT                        },
4562     { Xemerald,                 EL_EMERALD                      },
4563     { Xdiamond,                 EL_DIAMOND                      },
4564     { Xdrip_fall,               EL_AMOEBA_DROP                  },
4565     { Xbomb,                    EL_BOMB                         },
4566     { Xballoon,                 EL_BALLOON                      },
4567     { Xgrass,                   EL_EMC_GRASS                    },
4568     { Xdirt,                    EL_SAND                         },
4569     { Xacid_ne,                 EL_ACID_POOL_TOPRIGHT           },
4570     { Xacid_se,                 EL_ACID_POOL_BOTTOMRIGHT        },
4571     { Xacid_s,                  EL_ACID_POOL_BOTTOM             },
4572     { Xacid_sw,                 EL_ACID_POOL_BOTTOMLEFT         },
4573     { Xacid_nw,                 EL_ACID_POOL_TOPLEFT            },
4574     { Xacid_1,                  EL_ACID                         },
4575     { Xball_1,                  EL_EMC_GENERATOR_BALL           },
4576     { Xgrow_ns,                 EL_EMC_GROW                     },
4577     { Xwonderwall,              EL_MAGIC_WALL                   },
4578     { Xamoeba_1,                EL_AMOEBA_WET                   },
4579     { Xdoor_1,                  EL_EM_GATE_1                    },
4580     { Xdoor_2,                  EL_EM_GATE_2                    },
4581     { Xdoor_3,                  EL_EM_GATE_3                    },
4582     { Xdoor_4,                  EL_EM_GATE_4                    },
4583     { Xdoor_5,                  EL_EMC_GATE_5                   },
4584     { Xdoor_6,                  EL_EMC_GATE_6                   },
4585     { Xdoor_7,                  EL_EMC_GATE_7                   },
4586     { Xdoor_8,                  EL_EMC_GATE_8                   },
4587     { Xkey_1,                   EL_EM_KEY_1                     },
4588     { Xkey_2,                   EL_EM_KEY_2                     },
4589     { Xkey_3,                   EL_EM_KEY_3                     },
4590     { Xkey_4,                   EL_EM_KEY_4                     },
4591     { Xkey_5,                   EL_EMC_KEY_5                    },
4592     { Xkey_6,                   EL_EMC_KEY_6                    },
4593     { Xkey_7,                   EL_EMC_KEY_7                    },
4594     { Xkey_8,                   EL_EMC_KEY_8                    },
4595     { Xwind_n,                  EL_BALLOON_SWITCH_UP            },
4596     { Xwind_e,                  EL_BALLOON_SWITCH_RIGHT         },
4597     { Xwind_s,                  EL_BALLOON_SWITCH_DOWN          },
4598     { Xwind_w,                  EL_BALLOON_SWITCH_LEFT          },
4599     { Xwind_nesw,               EL_BALLOON_SWITCH_ANY           },
4600     { Xwind_stop,               EL_BALLOON_SWITCH_NONE          },
4601     { Xexit,                    EL_EXIT_CLOSED                  },
4602     { Xexit_1,                  EL_EXIT_OPEN                    },
4603     { Xdynamite,                EL_DYNAMITE                     },
4604     { Xdynamite_1,              EL_DYNAMITE_ACTIVE              },
4605     { Xbumper,                  EL_EMC_BUMPER                   },
4606     { Xwheel,                   EL_ROBOT_WHEEL                  },
4607     { Xswitch,                  EL_UNKNOWN                      },
4608     { Xsand,                    EL_QUICKSAND_EMPTY              },
4609     { Xsand_stone,              EL_QUICKSAND_FULL               },
4610     { Xplant,                   EL_EMC_PLANT                    },
4611     { Xlenses,                  EL_EMC_LENSES                   },
4612     { Xmagnify,                 EL_EMC_MAGNIFIER                },
4613     { Xdripper,                 EL_UNKNOWN                      },
4614     { Xfake_blank,              EL_INVISIBLE_WALL               },
4615     { Xfake_grass,              EL_INVISIBLE_SAND               },
4616     { Xfake_door_1,             EL_EM_GATE_1_GRAY               },
4617     { Xfake_door_2,             EL_EM_GATE_2_GRAY               },
4618     { Xfake_door_3,             EL_EM_GATE_3_GRAY               },
4619     { Xfake_door_4,             EL_EM_GATE_4_GRAY               },
4620     { Xfake_door_5,             EL_EMC_GATE_5_GRAY              },
4621     { Xfake_door_6,             EL_EMC_GATE_6_GRAY              },
4622     { Xfake_door_7,             EL_EMC_GATE_7_GRAY              },
4623     { Xfake_door_8,             EL_EMC_GATE_8_GRAY              },
4624     { Xsteel_1,                 EL_STEELWALL                    },
4625     { Xsteel_2,                 EL_UNKNOWN                      },
4626     { Xsteel_3,                 EL_EMC_STEELWALL_1              },
4627     { Xsteel_4,                 EL_UNKNOWN                      },
4628     { Xwall_1,                  EL_WALL                         },
4629     { Xwall_2,                  EL_UNKNOWN                      },
4630     { Xwall_3,                  EL_UNKNOWN                      },
4631     { Xwall_4,                  EL_UNKNOWN                      },
4632     { Xround_wall_1,            EL_WALL_SLIPPERY                },
4633     { Xround_wall_2,            EL_UNKNOWN                      },
4634     { Xround_wall_3,            EL_UNKNOWN                      },
4635     { Xround_wall_4,            EL_UNKNOWN                      },
4636     { Xdecor_1,                 EL_UNKNOWN                      },
4637     { Xdecor_2,                 EL_EMC_WALL_6                   },
4638     { Xdecor_3,                 EL_EMC_WALL_4                   },
4639     { Xdecor_4,                 EL_EMC_WALL_5                   },
4640     { Xdecor_5,                 EL_EMC_WALL_7                   },
4641     { Xdecor_6,                 EL_EMC_WALL_8                   },
4642     { Xdecor_7,                 EL_UNKNOWN                      },
4643     { Xdecor_8,                 EL_EMC_WALL_1                   },
4644     { Xdecor_9,                 EL_EMC_WALL_2                   },
4645     { Xdecor_10,                EL_EMC_WALL_3                   },
4646     { Xdecor_11,                EL_UNKNOWN                      },
4647     { Xdecor_12,                EL_UNKNOWN                      },
4648     { Xalpha_0,                 EL_CHAR('0')                    },
4649     { Xalpha_1,                 EL_CHAR('1')                    },
4650     { Xalpha_2,                 EL_CHAR('2')                    },
4651     { Xalpha_3,                 EL_CHAR('3')                    },
4652     { Xalpha_4,                 EL_CHAR('4')                    },
4653     { Xalpha_5,                 EL_CHAR('5')                    },
4654     { Xalpha_6,                 EL_CHAR('6')                    },
4655     { Xalpha_7,                 EL_CHAR('7')                    },
4656     { Xalpha_8,                 EL_CHAR('8')                    },
4657     { Xalpha_9,                 EL_CHAR('9')                    },
4658     { Xalpha_excla,             EL_CHAR('!')                    },
4659     { Xalpha_quote,             EL_CHAR('"')                    },
4660     { Xalpha_comma,             EL_CHAR(',')                    },
4661     { Xalpha_minus,             EL_CHAR('-')                    },
4662     { Xalpha_perio,             EL_CHAR('.')                    },
4663     { Xalpha_colon,             EL_CHAR(':')                    },
4664     { Xalpha_quest,             EL_CHAR('?')                    },
4665     { Xalpha_a,                 EL_CHAR('A')                    },
4666     { Xalpha_b,                 EL_CHAR('B')                    },
4667     { Xalpha_c,                 EL_CHAR('C')                    },
4668     { Xalpha_d,                 EL_CHAR('D')                    },
4669     { Xalpha_e,                 EL_CHAR('E')                    },
4670     { Xalpha_f,                 EL_CHAR('F')                    },
4671     { Xalpha_g,                 EL_CHAR('G')                    },
4672     { Xalpha_h,                 EL_CHAR('H')                    },
4673     { Xalpha_i,                 EL_CHAR('I')                    },
4674     { Xalpha_j,                 EL_CHAR('J')                    },
4675     { Xalpha_k,                 EL_CHAR('K')                    },
4676     { Xalpha_l,                 EL_CHAR('L')                    },
4677     { Xalpha_m,                 EL_CHAR('M')                    },
4678     { Xalpha_n,                 EL_CHAR('N')                    },
4679     { Xalpha_o,                 EL_CHAR('O')                    },
4680     { Xalpha_p,                 EL_CHAR('P')                    },
4681     { Xalpha_q,                 EL_CHAR('Q')                    },
4682     { Xalpha_r,                 EL_CHAR('R')                    },
4683     { Xalpha_s,                 EL_CHAR('S')                    },
4684     { Xalpha_t,                 EL_CHAR('T')                    },
4685     { Xalpha_u,                 EL_CHAR('U')                    },
4686     { Xalpha_v,                 EL_CHAR('V')                    },
4687     { Xalpha_w,                 EL_CHAR('W')                    },
4688     { Xalpha_x,                 EL_CHAR('X')                    },
4689     { Xalpha_y,                 EL_CHAR('Y')                    },
4690     { Xalpha_z,                 EL_CHAR('Z')                    },
4691     { Xalpha_arrow_e,           EL_CHAR('>')                    },
4692     { Xalpha_arrow_w,           EL_CHAR('<')                    },
4693     { Xalpha_copyr,             EL_CHAR('©')                    },
4694
4695     { Zplayer,                  EL_PLAYER_1                     },
4696     { Zplayer,                  EL_PLAYER_2                     },
4697     { Zplayer,                  EL_PLAYER_3                     },
4698     { Zplayer,                  EL_PLAYER_4                     },
4699
4700     { ZBORDER,                  EL_EMC_LEVEL_BORDER             },
4701
4702     { -1,                       -1                              }
4703   };
4704
4705   if (!mapping_initialized)
4706   {
4707     int i;
4708
4709     /* return "Xalpha_quest" for all undefined elements in mapping array */
4710     for (i = 0; i < NUM_FILE_ELEMENTS; i++)
4711       mapping_RND_to_EM[i] = Xalpha_quest;
4712
4713     for (i = 0; mapping_RND_to_EM_list[i].element_rnd != -1; i++)
4714       mapping_RND_to_EM[mapping_RND_to_EM_list[i].element_rnd] =
4715         mapping_RND_to_EM_list[i].element_em;
4716
4717     mapping_initialized = TRUE;
4718   }
4719
4720   if (element_rnd >= 0 && element_rnd < NUM_FILE_ELEMENTS)
4721     return mapping_RND_to_EM[element_rnd];
4722
4723   Error(ERR_WARN, "invalid RND level element %d", element_rnd);
4724
4725   return EL_UNKNOWN;
4726 }
4727
4728 int map_element_EM_to_RND(int element_em)
4729 {
4730   static unsigned short mapping_EM_to_RND[TILE_MAX];
4731   static boolean mapping_initialized = FALSE;
4732
4733   struct
4734   {
4735     int element_em;
4736     int element_rnd;
4737   }
4738   mapping_EM_to_RND_list[] =
4739   {
4740     { Xblank,                   EL_EMPTY                        },
4741     { Yacid_splash_eB,          EL_EMPTY                        },
4742     { Yacid_splash_wB,          EL_EMPTY                        },
4743
4744 #ifdef EM_ENGINE_BAD_ROLL
4745     { Xstone_force_e,           EL_ROCK                         },
4746     { Xstone_force_w,           EL_ROCK                         },
4747     { Xnut_force_e,             EL_NUT                          },
4748     { Xnut_force_w,             EL_NUT                          },
4749     { Xspring_force_e,          EL_SPRING                       },
4750     { Xspring_force_w,          EL_SPRING                       },
4751     { Xemerald_force_e,         EL_EMERALD                      },
4752     { Xemerald_force_w,         EL_EMERALD                      },
4753     { Xdiamond_force_e,         EL_DIAMOND                      },
4754     { Xdiamond_force_w,         EL_DIAMOND                      },
4755     { Xbomb_force_e,            EL_BOMB                         },
4756     { Xbomb_force_w,            EL_BOMB                         },
4757 #endif
4758
4759     { Xstone,                   EL_ROCK                         },
4760     { Xstone_pause,             EL_ROCK                         },
4761     { Xstone_fall,              EL_ROCK                         },
4762     { Ystone_s,                 EL_ROCK                         },
4763     { Ystone_sB,                EL_ROCK                         },
4764     { Ystone_e,                 EL_ROCK                         },
4765     { Ystone_eB,                EL_ROCK                         },
4766     { Ystone_w,                 EL_ROCK                         },
4767     { Ystone_wB,                EL_ROCK                         },
4768     { Xnut,                     EL_NUT                          },
4769     { Xnut_pause,               EL_NUT                          },
4770     { Xnut_fall,                EL_NUT                          },
4771     { Ynut_s,                   EL_NUT                          },
4772     { Ynut_sB,                  EL_NUT                          },
4773     { Ynut_e,                   EL_NUT                          },
4774     { Ynut_eB,                  EL_NUT                          },
4775     { Ynut_w,                   EL_NUT                          },
4776     { Ynut_wB,                  EL_NUT                          },
4777     { Xbug_n,                   EL_BUG_UP                       },
4778     { Xbug_e,                   EL_BUG_RIGHT                    },
4779     { Xbug_s,                   EL_BUG_DOWN                     },
4780     { Xbug_w,                   EL_BUG_LEFT                     },
4781     { Xbug_gon,                 EL_BUG_UP                       },
4782     { Xbug_goe,                 EL_BUG_RIGHT                    },
4783     { Xbug_gos,                 EL_BUG_DOWN                     },
4784     { Xbug_gow,                 EL_BUG_LEFT                     },
4785     { Ybug_n,                   EL_BUG_UP                       },
4786     { Ybug_nB,                  EL_BUG_UP                       },
4787     { Ybug_e,                   EL_BUG_RIGHT                    },
4788     { Ybug_eB,                  EL_BUG_RIGHT                    },
4789     { Ybug_s,                   EL_BUG_DOWN                     },
4790     { Ybug_sB,                  EL_BUG_DOWN                     },
4791     { Ybug_w,                   EL_BUG_LEFT                     },
4792     { Ybug_wB,                  EL_BUG_LEFT                     },
4793     { Ybug_w_n,                 EL_BUG_UP                       },
4794     { Ybug_n_e,                 EL_BUG_RIGHT                    },
4795     { Ybug_e_s,                 EL_BUG_DOWN                     },
4796     { Ybug_s_w,                 EL_BUG_LEFT                     },
4797     { Ybug_e_n,                 EL_BUG_UP                       },
4798     { Ybug_s_e,                 EL_BUG_RIGHT                    },
4799     { Ybug_w_s,                 EL_BUG_DOWN                     },
4800     { Ybug_n_w,                 EL_BUG_LEFT                     },
4801     { Ybug_stone,               EL_ROCK                         },
4802     { Ybug_spring,              EL_SPRING                       },
4803     { Xtank_n,                  EL_SPACESHIP_UP                 },
4804     { Xtank_e,                  EL_SPACESHIP_RIGHT              },
4805     { Xtank_s,                  EL_SPACESHIP_DOWN               },
4806     { Xtank_w,                  EL_SPACESHIP_LEFT               },
4807     { Xtank_gon,                EL_SPACESHIP_UP                 },
4808     { Xtank_goe,                EL_SPACESHIP_RIGHT              },
4809     { Xtank_gos,                EL_SPACESHIP_DOWN               },
4810     { Xtank_gow,                EL_SPACESHIP_LEFT               },
4811     { Ytank_n,                  EL_SPACESHIP_UP                 },
4812     { Ytank_nB,                 EL_SPACESHIP_UP                 },
4813     { Ytank_e,                  EL_SPACESHIP_RIGHT              },
4814     { Ytank_eB,                 EL_SPACESHIP_RIGHT              },
4815     { Ytank_s,                  EL_SPACESHIP_DOWN               },
4816     { Ytank_sB,                 EL_SPACESHIP_DOWN               },
4817     { Ytank_w,                  EL_SPACESHIP_LEFT               },
4818     { Ytank_wB,                 EL_SPACESHIP_LEFT               },
4819     { Ytank_w_n,                EL_SPACESHIP_UP                 },
4820     { Ytank_n_e,                EL_SPACESHIP_RIGHT              },
4821     { Ytank_e_s,                EL_SPACESHIP_DOWN               },
4822     { Ytank_s_w,                EL_SPACESHIP_LEFT               },
4823     { Ytank_e_n,                EL_SPACESHIP_UP                 },
4824     { Ytank_s_e,                EL_SPACESHIP_RIGHT              },
4825     { Ytank_w_s,                EL_SPACESHIP_DOWN               },
4826     { Ytank_n_w,                EL_SPACESHIP_LEFT               },
4827     { Ytank_stone,              EL_ROCK                         },
4828     { Ytank_spring,             EL_SPRING                       },
4829     { Xandroid,                 EL_EMC_ANDROID                  },
4830     { Xandroid_1_n,             EL_EMC_ANDROID_UP               },
4831     { Xandroid_2_n,             EL_EMC_ANDROID_UP               },
4832     { Xandroid_1_e,             EL_EMC_ANDROID_RIGHT            },
4833     { Xandroid_2_e,             EL_EMC_ANDROID_RIGHT            },
4834     { Xandroid_1_w,             EL_EMC_ANDROID_LEFT             },
4835     { Xandroid_2_w,             EL_EMC_ANDROID_LEFT             },
4836     { Xandroid_1_s,             EL_EMC_ANDROID_DOWN             },
4837     { Xandroid_2_s,             EL_EMC_ANDROID_DOWN             },
4838     { Yandroid_n,               EL_EMC_ANDROID_UP               },
4839     { Yandroid_nB,              EL_EMC_ANDROID_UP               },
4840     { Yandroid_ne,              EL_EMC_ANDROID_RIGHT_UP         },
4841     { Yandroid_neB,             EL_EMC_ANDROID_RIGHT_UP         },
4842     { Yandroid_e,               EL_EMC_ANDROID_RIGHT            },
4843     { Yandroid_eB,              EL_EMC_ANDROID_RIGHT            },
4844     { Yandroid_se,              EL_EMC_ANDROID_RIGHT_DOWN       },
4845     { Yandroid_seB,             EL_EMC_ANDROID_RIGHT_DOWN       },
4846     { Yandroid_s,               EL_EMC_ANDROID_DOWN             },
4847     { Yandroid_sB,              EL_EMC_ANDROID_DOWN             },
4848     { Yandroid_sw,              EL_EMC_ANDROID_LEFT_DOWN        },
4849     { Yandroid_swB,             EL_EMC_ANDROID_LEFT_DOWN        },
4850     { Yandroid_w,               EL_EMC_ANDROID_LEFT             },
4851     { Yandroid_wB,              EL_EMC_ANDROID_LEFT             },
4852     { Yandroid_nw,              EL_EMC_ANDROID_LEFT_UP          },
4853     { Yandroid_nwB,             EL_EMC_ANDROID_LEFT_UP          },
4854     { Xspring,                  EL_SPRING                       },
4855     { Xspring_pause,            EL_SPRING                       },
4856     { Xspring_e,                EL_SPRING                       },
4857     { Xspring_w,                EL_SPRING                       },
4858     { Xspring_fall,             EL_SPRING                       },
4859     { Yspring_s,                EL_SPRING                       },
4860     { Yspring_sB,               EL_SPRING                       },
4861     { Yspring_e,                EL_SPRING                       },
4862     { Yspring_eB,               EL_SPRING                       },
4863     { Yspring_w,                EL_SPRING                       },
4864     { Yspring_wB,               EL_SPRING                       },
4865     { Yspring_kill_e,           EL_SPRING                       },
4866     { Yspring_kill_eB,          EL_SPRING                       },
4867     { Yspring_kill_w,           EL_SPRING                       },
4868     { Yspring_kill_wB,          EL_SPRING                       },
4869     { Xeater_n,                 EL_YAMYAM                       },
4870     { Xeater_e,                 EL_YAMYAM                       },
4871     { Xeater_w,                 EL_YAMYAM                       },
4872     { Xeater_s,                 EL_YAMYAM                       },
4873     { Yeater_n,                 EL_YAMYAM                       },
4874     { Yeater_nB,                EL_YAMYAM                       },
4875     { Yeater_e,                 EL_YAMYAM                       },
4876     { Yeater_eB,                EL_YAMYAM                       },
4877     { Yeater_s,                 EL_YAMYAM                       },
4878     { Yeater_sB,                EL_YAMYAM                       },
4879     { Yeater_w,                 EL_YAMYAM                       },
4880     { Yeater_wB,                EL_YAMYAM                       },
4881     { Yeater_stone,             EL_ROCK                         },
4882     { Yeater_spring,            EL_SPRING                       },
4883     { Xalien,                   EL_ROBOT                        },
4884     { Xalien_pause,             EL_ROBOT                        },
4885     { Yalien_n,                 EL_ROBOT                        },
4886     { Yalien_nB,                EL_ROBOT                        },
4887     { Yalien_e,                 EL_ROBOT                        },
4888     { Yalien_eB,                EL_ROBOT                        },
4889     { Yalien_s,                 EL_ROBOT                        },
4890     { Yalien_sB,                EL_ROBOT                        },
4891     { Yalien_w,                 EL_ROBOT                        },
4892     { Yalien_wB,                EL_ROBOT                        },
4893     { Yalien_stone,             EL_ROCK                         },
4894     { Yalien_spring,            EL_SPRING                       },
4895     { Xemerald,                 EL_EMERALD                      },
4896     { Xemerald_pause,           EL_EMERALD                      },
4897     { Xemerald_fall,            EL_EMERALD                      },
4898     { Xemerald_shine,           EL_EMERALD                      },
4899     { Yemerald_s,               EL_EMERALD                      },
4900     { Yemerald_sB,              EL_EMERALD                      },
4901     { Yemerald_e,               EL_EMERALD                      },
4902     { Yemerald_eB,              EL_EMERALD                      },
4903     { Yemerald_w,               EL_EMERALD                      },
4904     { Yemerald_wB,              EL_EMERALD                      },
4905     { Yemerald_eat,             EL_EMERALD                      },
4906     { Yemerald_stone,           EL_ROCK                         },
4907     { Xdiamond,                 EL_DIAMOND                      },
4908     { Xdiamond_pause,           EL_DIAMOND                      },
4909     { Xdiamond_fall,            EL_DIAMOND                      },
4910     { Xdiamond_shine,           EL_DIAMOND                      },
4911     { Ydiamond_s,               EL_DIAMOND                      },
4912     { Ydiamond_sB,              EL_DIAMOND                      },
4913     { Ydiamond_e,               EL_DIAMOND                      },
4914     { Ydiamond_eB,              EL_DIAMOND                      },
4915     { Ydiamond_w,               EL_DIAMOND                      },
4916     { Ydiamond_wB,              EL_DIAMOND                      },
4917     { Ydiamond_eat,             EL_DIAMOND                      },
4918     { Ydiamond_stone,           EL_ROCK                         },
4919     { Xdrip_fall,               EL_AMOEBA_DROP                  },
4920     { Xdrip_stretch,            EL_AMOEBA_DROP                  },
4921     { Xdrip_stretchB,           EL_AMOEBA_DROP                  },
4922     { Xdrip_eat,                EL_AMOEBA_DROP                  },
4923     { Ydrip_s1,                 EL_AMOEBA_DROP                  },
4924     { Ydrip_s1B,                EL_AMOEBA_DROP                  },
4925     { Ydrip_s2,                 EL_AMOEBA_DROP                  },
4926     { Ydrip_s2B,                EL_AMOEBA_DROP                  },
4927     { Xbomb,                    EL_BOMB                         },
4928     { Xbomb_pause,              EL_BOMB                         },
4929     { Xbomb_fall,               EL_BOMB                         },
4930     { Ybomb_s,                  EL_BOMB                         },
4931     { Ybomb_sB,                 EL_BOMB                         },
4932     { Ybomb_e,                  EL_BOMB                         },
4933     { Ybomb_eB,                 EL_BOMB                         },
4934     { Ybomb_w,                  EL_BOMB                         },
4935     { Ybomb_wB,                 EL_BOMB                         },
4936     { Ybomb_eat,                EL_BOMB                         },
4937     { Xballoon,                 EL_BALLOON                      },
4938     { Yballoon_n,               EL_BALLOON                      },
4939     { Yballoon_nB,              EL_BALLOON                      },
4940     { Yballoon_e,               EL_BALLOON                      },
4941     { Yballoon_eB,              EL_BALLOON                      },
4942     { Yballoon_s,               EL_BALLOON                      },
4943     { Yballoon_sB,              EL_BALLOON                      },
4944     { Yballoon_w,               EL_BALLOON                      },
4945     { Yballoon_wB,              EL_BALLOON                      },
4946     { Xgrass,                   EL_SAND                         },
4947     { Ygrass_nB,                EL_SAND                         },
4948     { Ygrass_eB,                EL_SAND                         },
4949     { Ygrass_sB,                EL_SAND                         },
4950     { Ygrass_wB,                EL_SAND                         },
4951     { Xdirt,                    EL_SAND                         },
4952     { Ydirt_nB,                 EL_SAND                         },
4953     { Ydirt_eB,                 EL_SAND                         },
4954     { Ydirt_sB,                 EL_SAND                         },
4955     { Ydirt_wB,                 EL_SAND                         },
4956     { Xacid_ne,                 EL_ACID_POOL_TOPRIGHT           },
4957     { Xacid_se,                 EL_ACID_POOL_BOTTOMRIGHT        },
4958     { Xacid_s,                  EL_ACID_POOL_BOTTOM             },
4959     { Xacid_sw,                 EL_ACID_POOL_BOTTOMLEFT         },
4960     { Xacid_nw,                 EL_ACID_POOL_TOPLEFT            },
4961     { Xacid_1,                  EL_ACID                         },
4962     { Xacid_2,                  EL_ACID                         },
4963     { Xacid_3,                  EL_ACID                         },
4964     { Xacid_4,                  EL_ACID                         },
4965     { Xacid_5,                  EL_ACID                         },
4966     { Xacid_6,                  EL_ACID                         },
4967     { Xacid_7,                  EL_ACID                         },
4968     { Xacid_8,                  EL_ACID                         },
4969     { Xball_1,                  EL_EMC_GENERATOR_BALL           },
4970     { Xball_1B,                 EL_EMC_GENERATOR_BALL           },
4971     { Xball_2,                  EL_EMC_GENERATOR_BALL           },
4972     { Xball_2B,                 EL_EMC_GENERATOR_BALL           },
4973     { Yball_eat,                EL_EMC_GENERATOR_BALL           },
4974     { Xgrow_ns,                 EL_EMC_GROW                     },
4975     { Ygrow_ns_eat,             EL_EMC_GROW                     },
4976     { Xgrow_ew,                 EL_EMC_GROW                     },
4977     { Ygrow_ew_eat,             EL_EMC_GROW                     },
4978     { Xwonderwall,              EL_MAGIC_WALL                   },
4979     { XwonderwallB,             EL_MAGIC_WALL                   },
4980     { Xamoeba_1,                EL_AMOEBA_WET                   },
4981     { Xamoeba_2,                EL_AMOEBA_WET                   },
4982     { Xamoeba_3,                EL_AMOEBA_WET                   },
4983     { Xamoeba_4,                EL_AMOEBA_WET                   },
4984     { Xamoeba_5,                EL_AMOEBA_WET                   },
4985     { Xamoeba_6,                EL_AMOEBA_WET                   },
4986     { Xamoeba_7,                EL_AMOEBA_WET                   },
4987     { Xamoeba_8,                EL_AMOEBA_WET                   },
4988     { Xdoor_1,                  EL_EM_GATE_1                    },
4989     { Xdoor_2,                  EL_EM_GATE_2                    },
4990     { Xdoor_3,                  EL_EM_GATE_3                    },
4991     { Xdoor_4,                  EL_EM_GATE_4                    },
4992     { Xdoor_5,                  EL_EMC_GATE_5                   },
4993     { Xdoor_6,                  EL_EMC_GATE_6                   },
4994     { Xdoor_7,                  EL_EMC_GATE_7                   },
4995     { Xdoor_8,                  EL_EMC_GATE_8                   },
4996     { Xkey_1,                   EL_EM_KEY_1                     },
4997     { Xkey_2,                   EL_EM_KEY_2                     },
4998     { Xkey_3,                   EL_EM_KEY_3                     },
4999     { Xkey_4,                   EL_EM_KEY_4                     },
5000     { Xkey_5,                   EL_EMC_KEY_5                    },
5001     { Xkey_6,                   EL_EMC_KEY_6                    },
5002     { Xkey_7,                   EL_EMC_KEY_7                    },
5003     { Xkey_8,                   EL_EMC_KEY_8                    },
5004     { Xwind_n,                  EL_BALLOON_SWITCH_UP            },
5005     { Xwind_e,                  EL_BALLOON_SWITCH_RIGHT         },
5006     { Xwind_s,                  EL_BALLOON_SWITCH_DOWN          },
5007     { Xwind_w,                  EL_BALLOON_SWITCH_LEFT          },
5008     { Xwind_nesw,               EL_BALLOON_SWITCH_ANY           },
5009     { Xwind_stop,               EL_BALLOON_SWITCH_NONE          },
5010     { Xexit,                    EL_EXIT_CLOSED                  },
5011     { Xexit_1,                  EL_EXIT_OPEN                    },
5012     { Xexit_2,                  EL_EXIT_OPEN                    },
5013     { Xexit_3,                  EL_EXIT_OPEN                    },
5014     { Xdynamite,                EL_DYNAMITE                     },
5015     { Ydynamite_eat,            EL_DYNAMITE                     },
5016     { Xdynamite_1,              EL_DYNAMITE_ACTIVE              },
5017     { Xdynamite_2,              EL_DYNAMITE_ACTIVE              },
5018     { Xdynamite_3,              EL_DYNAMITE_ACTIVE              },
5019     { Xdynamite_4,              EL_DYNAMITE_ACTIVE              },
5020     { Xbumper,                  EL_EMC_BUMPER                   },
5021     { XbumperB,                 EL_EMC_BUMPER                   },
5022     { Xwheel,                   EL_ROBOT_WHEEL                  },
5023     { XwheelB,                  EL_ROBOT_WHEEL                  },
5024     { Xswitch,                  EL_UNKNOWN                      },
5025     { XswitchB,                 EL_UNKNOWN                      },
5026     { Xsand,                    EL_QUICKSAND_EMPTY              },
5027     { Xsand_stone,              EL_QUICKSAND_FULL               },
5028     { Xsand_stonein_1,          EL_QUICKSAND_FULL               },
5029     { Xsand_stonein_2,          EL_QUICKSAND_FULL               },
5030     { Xsand_stonein_3,          EL_QUICKSAND_FULL               },
5031     { Xsand_stonein_4,          EL_QUICKSAND_FULL               },
5032     { Xsand_stonesand_1,        EL_QUICKSAND_FULL               },
5033     { Xsand_stonesand_2,        EL_QUICKSAND_FULL               },
5034     { Xsand_stonesand_3,        EL_QUICKSAND_FULL               },
5035     { Xsand_stonesand_4,        EL_QUICKSAND_FULL               },
5036     { Xsand_stoneout_1,         EL_QUICKSAND_FULL               },
5037     { Xsand_stoneout_2,         EL_QUICKSAND_FULL               },
5038     { Xsand_sandstone_1,        EL_QUICKSAND_FULL               },
5039     { Xsand_sandstone_2,        EL_QUICKSAND_FULL               },
5040     { Xsand_sandstone_3,        EL_QUICKSAND_FULL               },
5041     { Xsand_sandstone_4,        EL_QUICKSAND_FULL               },
5042     { Xplant,                   EL_EMC_PLANT                    },
5043     { Yplant,                   EL_EMC_PLANT                    },
5044     { Xlenses,                  EL_EMC_LENSES                   },
5045     { Xmagnify,                 EL_EMC_MAGNIFIER                },
5046     { Xdripper,                 EL_UNKNOWN                      },
5047     { XdripperB,                EL_UNKNOWN                      },
5048     { Xfake_blank,              EL_INVISIBLE_WALL               },
5049     { Xfake_blankB,             EL_INVISIBLE_WALL               },
5050     { Xfake_grass,              EL_INVISIBLE_SAND               },
5051     { Xfake_grassB,             EL_INVISIBLE_SAND               },
5052     { Xfake_door_1,             EL_EM_GATE_1_GRAY               },
5053     { Xfake_door_2,             EL_EM_GATE_2_GRAY               },
5054     { Xfake_door_3,             EL_EM_GATE_3_GRAY               },
5055     { Xfake_door_4,             EL_EM_GATE_4_GRAY               },
5056     { Xfake_door_5,             EL_EMC_GATE_5_GRAY              },
5057     { Xfake_door_6,             EL_EMC_GATE_6_GRAY              },
5058     { Xfake_door_7,             EL_EMC_GATE_7_GRAY              },
5059     { Xfake_door_8,             EL_EMC_GATE_8_GRAY              },
5060     { Xsteel_1,                 EL_STEELWALL                    },
5061     { Xsteel_2,                 EL_UNKNOWN                      },
5062     { Xsteel_3,                 EL_EMC_STEELWALL_1              },
5063     { Xsteel_4,                 EL_UNKNOWN                      },
5064     { Xwall_1,                  EL_WALL                         },
5065     { Xwall_2,                  EL_UNKNOWN                      },
5066     { Xwall_3,                  EL_UNKNOWN                      },
5067     { Xwall_4,                  EL_UNKNOWN                      },
5068     { Xround_wall_1,            EL_WALL_SLIPPERY                },
5069     { Xround_wall_2,            EL_UNKNOWN                      },
5070     { Xround_wall_3,            EL_UNKNOWN                      },
5071     { Xround_wall_4,            EL_UNKNOWN                      },
5072     { Xdecor_1,                 EL_UNKNOWN                      },
5073     { Xdecor_2,                 EL_EMC_WALL_6                   },
5074     { Xdecor_3,                 EL_EMC_WALL_4                   },
5075     { Xdecor_4,                 EL_EMC_WALL_5                   },
5076     { Xdecor_5,                 EL_EMC_WALL_7                   },
5077     { Xdecor_6,                 EL_EMC_WALL_8                   },
5078     { Xdecor_7,                 EL_UNKNOWN                      },
5079     { Xdecor_8,                 EL_EMC_WALL_1                   },
5080     { Xdecor_9,                 EL_EMC_WALL_2                   },
5081     { Xdecor_10,                EL_EMC_WALL_3                   },
5082     { Xdecor_11,                EL_UNKNOWN                      },
5083     { Xdecor_12,                EL_UNKNOWN                      },
5084     { Xalpha_0,                 EL_CHAR('0')                    },
5085     { Xalpha_1,                 EL_CHAR('1')                    },
5086     { Xalpha_2,                 EL_CHAR('2')                    },
5087     { Xalpha_3,                 EL_CHAR('3')                    },
5088     { Xalpha_4,                 EL_CHAR('4')                    },
5089     { Xalpha_5,                 EL_CHAR('5')                    },
5090     { Xalpha_6,                 EL_CHAR('6')                    },
5091     { Xalpha_7,                 EL_CHAR('7')                    },
5092     { Xalpha_8,                 EL_CHAR('8')                    },
5093     { Xalpha_9,                 EL_CHAR('9')                    },
5094     { Xalpha_excla,             EL_CHAR('!')                    },
5095     { Xalpha_quote,             EL_CHAR('"')                    },
5096     { Xalpha_comma,             EL_CHAR(',')                    },
5097     { Xalpha_minus,             EL_CHAR('-')                    },
5098     { Xalpha_perio,             EL_CHAR('.')                    },
5099     { Xalpha_colon,             EL_CHAR(':')                    },
5100     { Xalpha_quest,             EL_CHAR('?')                    },
5101     { Xalpha_a,                 EL_CHAR('A')                    },
5102     { Xalpha_b,                 EL_CHAR('B')                    },
5103     { Xalpha_c,                 EL_CHAR('C')                    },
5104     { Xalpha_d,                 EL_CHAR('D')                    },
5105     { Xalpha_e,                 EL_CHAR('E')                    },
5106     { Xalpha_f,                 EL_CHAR('F')                    },
5107     { Xalpha_g,                 EL_CHAR('G')                    },
5108     { Xalpha_h,                 EL_CHAR('H')                    },
5109     { Xalpha_i,                 EL_CHAR('I')                    },
5110     { Xalpha_j,                 EL_CHAR('J')                    },
5111     { Xalpha_k,                 EL_CHAR('K')                    },
5112     { Xalpha_l,                 EL_CHAR('L')                    },
5113     { Xalpha_m,                 EL_CHAR('M')                    },
5114     { Xalpha_n,                 EL_CHAR('N')                    },
5115     { Xalpha_o,                 EL_CHAR('O')                    },
5116     { Xalpha_p,                 EL_CHAR('P')                    },
5117     { Xalpha_q,                 EL_CHAR('Q')                    },
5118     { Xalpha_r,                 EL_CHAR('R')                    },
5119     { Xalpha_s,                 EL_CHAR('S')                    },
5120     { Xalpha_t,                 EL_CHAR('T')                    },
5121     { Xalpha_u,                 EL_CHAR('U')                    },
5122     { Xalpha_v,                 EL_CHAR('V')                    },
5123     { Xalpha_w,                 EL_CHAR('W')                    },
5124     { Xalpha_x,                 EL_CHAR('X')                    },
5125     { Xalpha_y,                 EL_CHAR('Y')                    },
5126     { Xalpha_z,                 EL_CHAR('Z')                    },
5127     { Xalpha_arrow_e,           EL_CHAR('>')                    },
5128     { Xalpha_arrow_w,           EL_CHAR('<')                    },
5129     { Xalpha_copyr,             EL_CHAR('©')                    },
5130
5131     { Zplayer,                  EL_PLAYER_1                     },
5132
5133     { ZBORDER,                  EL_EMC_LEVEL_BORDER             },
5134
5135     { -1,                       -1                              }
5136   };
5137
5138   if (!mapping_initialized)
5139   {
5140     int i;
5141
5142     /* return "EL_UNKNOWN" for all undefined elements in mapping array */
5143     for (i = 0; i < TILE_MAX; i++)
5144       mapping_EM_to_RND[i] = EL_UNKNOWN;
5145
5146     for (i = 0; mapping_EM_to_RND_list[i].element_em != -1; i++)
5147       mapping_EM_to_RND[mapping_EM_to_RND_list[i].element_em] =
5148         mapping_EM_to_RND_list[i].element_rnd;
5149
5150     mapping_initialized = TRUE;
5151   }
5152
5153   if (element_em >= 0 && element_em < TILE_MAX)
5154     return mapping_EM_to_RND[element_em];
5155
5156   Error(ERR_WARN, "invalid EM level element %d", element_em);
5157
5158   return EL_UNKNOWN;
5159 }
5160
5161 #endif
5162
5163 int get_next_element(int element)
5164 {
5165   switch(element)
5166   {
5167     case EL_QUICKSAND_FILLING:          return EL_QUICKSAND_FULL;
5168     case EL_QUICKSAND_EMPTYING:         return EL_QUICKSAND_EMPTY;
5169     case EL_MAGIC_WALL_FILLING:         return EL_MAGIC_WALL_FULL;
5170     case EL_MAGIC_WALL_EMPTYING:        return EL_MAGIC_WALL_ACTIVE;
5171     case EL_BD_MAGIC_WALL_FILLING:      return EL_BD_MAGIC_WALL_FULL;
5172     case EL_BD_MAGIC_WALL_EMPTYING:     return EL_BD_MAGIC_WALL_ACTIVE;
5173     case EL_AMOEBA_DROPPING:            return EL_AMOEBA_WET;
5174
5175     default:                            return element;
5176   }
5177 }
5178
5179 int el_act_dir2img(int element, int action, int direction)
5180 {
5181   element = GFX_ELEMENT(element);
5182   direction = MV_DIR_BIT(direction);    /* default: MV_NO_MOVING => MV_DOWN */
5183
5184   return element_info[element].direction_graphic[action][direction];
5185 }
5186
5187 static int el_act_dir2crm(int element, int action, int direction)
5188 {
5189   element = GFX_ELEMENT(element);
5190   direction = MV_DIR_BIT(direction);    /* default: MV_NO_MOVING => MV_DOWN */
5191
5192   return element_info[element].direction_crumbled[action][direction];
5193 }
5194
5195 int el_act2img(int element, int action)
5196 {
5197   element = GFX_ELEMENT(element);
5198
5199   return element_info[element].graphic[action];
5200 }
5201
5202 int el_act2crm(int element, int action)
5203 {
5204   element = GFX_ELEMENT(element);
5205
5206   return element_info[element].crumbled[action];
5207 }
5208
5209 int el_dir2img(int element, int direction)
5210 {
5211   element = GFX_ELEMENT(element);
5212
5213   return el_act_dir2img(element, ACTION_DEFAULT, direction);
5214 }
5215
5216 int el2baseimg(int element)
5217 {
5218   return element_info[element].graphic[ACTION_DEFAULT];
5219 }
5220
5221 int el2img(int element)
5222 {
5223   element = GFX_ELEMENT(element);
5224
5225   return element_info[element].graphic[ACTION_DEFAULT];
5226 }
5227
5228 int el2edimg(int element)
5229 {
5230   element = GFX_ELEMENT(element);
5231
5232   return element_info[element].special_graphic[GFX_SPECIAL_ARG_EDITOR];
5233 }
5234
5235 int el2preimg(int element)
5236 {
5237   element = GFX_ELEMENT(element);
5238
5239   return element_info[element].special_graphic[GFX_SPECIAL_ARG_PREVIEW];
5240 }
5241
5242 int getGameFrameDelay_EM(int native_em_game_frame_delay)
5243 {
5244   return (GameFrameDelay == GAME_FRAME_DELAY ? native_em_game_frame_delay :
5245           GameFrameDelay);
5246 }