1 /***********************************************************
2 * Rocks'n'Diamonds -- McDuffin Strikes Back! *
3 *----------------------------------------------------------*
4 * (c) 1995-2002 Artsoft Entertainment *
6 * Detmolder Strasse 189 *
9 * e-mail: info@artsoft.org *
10 *----------------------------------------------------------*
12 ***********************************************************/
14 #include "libgame/libgame.h"
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
32 #define NUM_TOOL_BUTTONS 7
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);
40 static struct GadgetInfo *tool_gadget[NUM_TOOL_BUTTONS];
41 static int request_gadget_id = -1;
43 static char *print_if_not_empty(int element)
45 static char *s = NULL;
46 char *token_name = element_info[element].token_name;
51 s = checked_malloc(strlen(token_name) + 10 + 1);
53 if (element != EL_EMPTY)
54 sprintf(s, "%d\t['%s']", element, token_name);
56 sprintf(s, "%d", element);
61 void DumpTile(int x, int y)
67 printf("Field Info: SCREEN(%d, %d), LEVEL(%d, %d)\n", sx, sy, x, y);
70 if (!IN_LEV_FIELD(x, y))
72 printf("(not in level field)\n");
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(" Count: %d\n", Count[x][y]);
89 printf(" GfxElement: %d\n", GfxElement[x][y]);
90 printf(" GfxAction: %d\n", GfxAction[x][y]);
91 printf(" GfxFrame: %d\n", GfxFrame[x][y]);
95 void SetDrawtoField(int mode)
97 if (mode == DRAW_BUFFERED && setup.soft_scrolling)
108 drawto_field = fieldbuffer;
110 else /* DRAW_DIRECT, DRAW_BACKBUFFER */
116 BX2 = SCR_FIELDX - 1;
117 BY2 = SCR_FIELDY - 1;
121 drawto_field = (mode == DRAW_DIRECT ? window : backbuffer);
125 void RedrawPlayfield(boolean force_redraw, int x, int y, int width, int height)
127 if (game_status == GAME_MODE_PLAYING &&
128 level.game_engine_type == GAME_ENGINE_TYPE_EM)
130 BlitScreenToBitmap_EM(backbuffer);
132 else if (game_status == GAME_MODE_PLAYING && !game.envelope_active)
138 width = gfx.sxsize + 2 * TILEX;
139 height = gfx.sysize + 2 * TILEY;
142 if (force_redraw || setup.direct_draw)
145 int x1 = (x - SX) / TILEX, y1 = (y - SY) / TILEY;
146 int x2 = (x - SX + width) / TILEX, y2 = (y - SY + height) / TILEY;
148 if (setup.direct_draw)
149 SetDrawtoField(DRAW_BACKBUFFER);
151 for (xx = BX1; xx <= BX2; xx++)
152 for (yy = BY1; yy <= BY2; yy++)
153 if (xx >= x1 && xx <= x2 && yy >= y1 && yy <= y2)
154 DrawScreenField(xx, yy);
157 if (setup.direct_draw)
158 SetDrawtoField(DRAW_DIRECT);
161 if (setup.soft_scrolling)
163 int fx = FX, fy = FY;
165 fx += (ScreenMovDir & (MV_LEFT|MV_RIGHT) ? ScreenGfxPos : 0);
166 fy += (ScreenMovDir & (MV_UP|MV_DOWN) ? ScreenGfxPos : 0);
168 BlitBitmap(fieldbuffer, backbuffer, fx,fy, SXSIZE,SYSIZE, SX,SY);
172 BlitBitmap(drawto, window, x, y, width, height, x, y);
178 DrawBuffer *buffer = (drawto_field == window ? backbuffer : drawto_field);
180 if (setup.direct_draw && game_status == GAME_MODE_PLAYING)
181 redraw_mask &= ~REDRAW_MAIN;
183 if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD)
184 redraw_mask |= REDRAW_FIELD;
186 if (redraw_mask & REDRAW_FIELD)
187 redraw_mask &= ~REDRAW_TILES;
189 if (redraw_mask == REDRAW_NONE)
192 if (global.fps_slowdown && game_status == GAME_MODE_PLAYING)
194 static boolean last_frame_skipped = FALSE;
195 boolean skip_even_when_not_scrolling = TRUE;
196 boolean just_scrolling = (ScreenMovDir != 0);
197 boolean verbose = FALSE;
199 if (global.fps_slowdown_factor > 1 &&
200 (FrameCounter % global.fps_slowdown_factor) &&
201 (just_scrolling || skip_even_when_not_scrolling))
203 redraw_mask &= ~REDRAW_MAIN;
205 last_frame_skipped = TRUE;
208 printf("FRAME SKIPPED\n");
212 if (last_frame_skipped)
213 redraw_mask |= REDRAW_FIELD;
215 last_frame_skipped = FALSE;
218 printf("frame not skipped\n");
222 /* synchronize X11 graphics at this point; if we would synchronize the
223 display immediately after the buffer switching (after the XFlush),
224 this could mean that we have to wait for the graphics to complete,
225 although we could go on doing calculations for the next frame */
229 if (redraw_mask & REDRAW_ALL)
231 BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
235 if (redraw_mask & REDRAW_FIELD)
237 if (game_status != GAME_MODE_PLAYING ||
238 redraw_mask & REDRAW_FROM_BACKBUFFER)
240 BlitBitmap(backbuffer, window,
241 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE, REAL_SX, REAL_SY);
245 int fx = FX, fy = FY;
247 if (setup.soft_scrolling)
249 fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
250 fy += (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
253 if (setup.soft_scrolling ||
254 ABS(ScreenMovPos) + ScrollStepSize == TILEX ||
255 ABS(ScreenMovPos) == ScrollStepSize ||
256 redraw_tiles > REDRAWTILES_THRESHOLD)
258 BlitBitmap(buffer, window, fx, fy, SXSIZE, SYSIZE, SX, SY);
262 printf("redrawing all (ScreenGfxPos == %d) because %s\n",
264 (setup.soft_scrolling ?
265 "setup.soft_scrolling" :
266 ABS(ScreenGfxPos) + ScrollStepSize == TILEX ?
267 "ABS(ScreenGfxPos) + ScrollStepSize == TILEX" :
268 ABS(ScreenGfxPos) == ScrollStepSize ?
269 "ABS(ScreenGfxPos) == ScrollStepSize" :
270 "redraw_tiles > REDRAWTILES_THRESHOLD"));
276 redraw_mask &= ~REDRAW_MAIN;
279 if (redraw_mask & REDRAW_DOORS)
281 if (redraw_mask & REDRAW_DOOR_1)
282 BlitBitmap(backbuffer, window, DX, DY, DXSIZE, DYSIZE, DX, DY);
284 if (redraw_mask & REDRAW_DOOR_2)
285 BlitBitmap(backbuffer, window, VX, VY, VXSIZE, VYSIZE, VX, VY);
287 if (redraw_mask & REDRAW_DOOR_3)
288 BlitBitmap(backbuffer, window, EX, EY, EXSIZE, EYSIZE, EX, EY);
290 redraw_mask &= ~REDRAW_DOORS;
293 if (redraw_mask & REDRAW_MICROLEVEL)
295 BlitBitmap(backbuffer, window, SX, SY + 10 * TILEY, SXSIZE, 7 * TILEY,
296 SX, SY + 10 * TILEY);
298 redraw_mask &= ~REDRAW_MICROLEVEL;
301 if (redraw_mask & REDRAW_TILES)
303 for (x = 0; x < SCR_FIELDX; x++)
304 for (y = 0 ; y < SCR_FIELDY; y++)
305 if (redraw[redraw_x1 + x][redraw_y1 + y])
306 BlitBitmap(buffer, window,
307 FX + x * TILEX, FY + y * TILEY, TILEX, TILEY,
308 SX + x * TILEX, SY + y * TILEY);
311 if (redraw_mask & REDRAW_FPS) /* display frames per second */
316 sprintf(info1, " (only every %d. frame)", global.fps_slowdown_factor);
317 if (!global.fps_slowdown)
320 sprintf(text, "%.1f fps%s", global.frames_per_second, info1);
321 DrawTextExt(window, SX, SY, text, FONT_TEXT_2, BLIT_OPAQUE);
326 for (x = 0; x < MAX_BUF_XSIZE; x++)
327 for (y = 0; y < MAX_BUF_YSIZE; y++)
330 redraw_mask = REDRAW_NONE;
336 long fading_delay = 300;
338 if (setup.fading && (redraw_mask & REDRAW_FIELD))
345 ClearRectangle(window, REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
348 for (i = 0; i < 2 * FULL_SYSIZE; i++)
350 for (y = 0; y < FULL_SYSIZE; y++)
352 BlitBitmap(backbuffer, window,
353 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
361 for (i = 1; i < FULL_SYSIZE; i+=2)
362 BlitBitmap(backbuffer, window,
363 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
369 SetClipOrigin(clip_gc[PIX_FADEMASK], 0, 0);
370 BlitBitmapMasked(backbuffer, window,
371 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
376 SetClipOrigin(clip_gc[PIX_FADEMASK], -1, -1);
377 BlitBitmapMasked(backbuffer, window,
378 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
383 SetClipOrigin(clip_gc[PIX_FADEMASK], 0, -1);
384 BlitBitmapMasked(backbuffer, window,
385 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
390 SetClipOrigin(clip_gc[PIX_FADEMASK], -1, 0);
391 BlitBitmapMasked(backbuffer, window,
392 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
397 redraw_mask &= ~REDRAW_MAIN;
404 void SetMainBackgroundImageIfDefined(int graphic)
406 if (graphic_info[graphic].bitmap)
407 SetMainBackgroundImage(graphic);
410 void SetMainBackgroundImage(int graphic)
412 SetMainBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
413 graphic_info[graphic].bitmap ?
414 graphic_info[graphic].bitmap :
415 graphic_info[IMG_BACKGROUND].bitmap);
418 void SetDoorBackgroundImage(int graphic)
420 SetDoorBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
421 graphic_info[graphic].bitmap ?
422 graphic_info[graphic].bitmap :
423 graphic_info[IMG_BACKGROUND].bitmap);
426 void DrawBackground(int dst_x, int dst_y, int width, int height)
428 ClearRectangleOnBackground(backbuffer, dst_x, dst_y, width, height);
430 redraw_mask |= REDRAW_FIELD;
435 DrawBackground(REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
437 if (setup.soft_scrolling && game_status == GAME_MODE_PLAYING)
439 ClearRectangle(fieldbuffer, 0, 0, FXSIZE, FYSIZE);
440 SetDrawtoField(DRAW_BUFFERED);
443 SetDrawtoField(DRAW_BACKBUFFER);
445 if (setup.direct_draw && game_status == GAME_MODE_PLAYING)
447 ClearRectangle(window, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
448 SetDrawtoField(DRAW_DIRECT);
452 void MarkTileDirty(int x, int y)
454 int xx = redraw_x1 + x;
455 int yy = redraw_y1 + y;
460 redraw[xx][yy] = TRUE;
461 redraw_mask |= REDRAW_TILES;
464 void SetBorderElement()
468 BorderElement = EL_EMPTY;
470 for (y = 0; y < lev_fieldy && BorderElement == EL_EMPTY; y++)
472 for (x = 0; x < lev_fieldx; x++)
474 if (!IS_INDESTRUCTIBLE(Feld[x][y]))
475 BorderElement = EL_STEELWALL;
477 if (y != 0 && y != lev_fieldy - 1 && x != lev_fieldx - 1)
483 void SetRandomAnimationValue(int x, int y)
485 gfx.anim_random_frame = GfxRandom[x][y];
488 inline int getGraphicAnimationFrame(int graphic, int sync_frame)
490 /* animation synchronized with global frame counter, not move position */
491 if (graphic_info[graphic].anim_global_sync || sync_frame < 0)
492 sync_frame = FrameCounter;
494 return getAnimationFrame(graphic_info[graphic].anim_frames,
495 graphic_info[graphic].anim_delay,
496 graphic_info[graphic].anim_mode,
497 graphic_info[graphic].anim_start_frame,
501 inline void getGraphicSourceExt(int graphic, int frame, Bitmap **bitmap,
502 int *x, int *y, boolean get_backside)
504 struct GraphicInfo *g = &graphic_info[graphic];
505 int src_x = g->src_x + (get_backside ? g->offset2_x : 0);
506 int src_y = g->src_y + (get_backside ? g->offset2_y : 0);
510 if (g->offset_y == 0) /* frames are ordered horizontally */
512 int max_width = g->anim_frames_per_line * g->width;
513 int pos = (src_y / g->height) * max_width + src_x + frame * g->offset_x;
515 *x = pos % max_width;
516 *y = src_y % g->height + pos / max_width * g->height;
518 else if (g->offset_x == 0) /* frames are ordered vertically */
520 int max_height = g->anim_frames_per_line * g->height;
521 int pos = (src_x / g->width) * max_height + src_y + frame * g->offset_y;
523 *x = src_x % g->width + pos / max_height * g->width;
524 *y = pos % max_height;
526 else /* frames are ordered diagonally */
528 *x = src_x + frame * g->offset_x;
529 *y = src_y + frame * g->offset_y;
533 void getGraphicSource(int graphic, int frame, Bitmap **bitmap, int *x, int *y)
535 getGraphicSourceExt(graphic, frame, bitmap, x, y, FALSE);
538 void DrawGraphic(int x, int y, int graphic, int frame)
541 if (!IN_SCR_FIELD(x, y))
543 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
544 printf("DrawGraphic(): This should never happen!\n");
549 DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic, frame);
553 void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
559 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
560 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
563 void DrawGraphicThruMask(int x, int y, int graphic, int frame)
566 if (!IN_SCR_FIELD(x, y))
568 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
569 printf("DrawGraphicThruMask(): This should never happen!\n");
574 DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY, graphic,
579 void DrawGraphicThruMaskExt(DrawBuffer *d, int dst_x, int dst_y, int graphic,
585 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
587 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
588 dst_x - src_x, dst_y - src_y);
589 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dst_x, dst_y);
592 void DrawMiniGraphic(int x, int y, int graphic)
594 DrawMiniGraphicExt(drawto, SX + x * MINI_TILEX,SY + y * MINI_TILEY, graphic);
595 MarkTileDirty(x / 2, y / 2);
598 void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
600 struct GraphicInfo *g = &graphic_info[graphic];
602 int mini_starty = g->bitmap->height * 2 / 3;
605 *x = mini_startx + g->src_x / 2;
606 *y = mini_starty + g->src_y / 2;
609 void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
614 getMiniGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
615 BlitBitmap(src_bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
618 inline static void DrawGraphicShiftedNormal(int x, int y, int dx, int dy,
619 int graphic, int frame,
620 int cut_mode, int mask_mode)
625 int width = TILEX, height = TILEY;
628 if (dx || dy) /* shifted graphic */
630 if (x < BX1) /* object enters playfield from the left */
637 else if (x > BX2) /* object enters playfield from the right */
643 else if (x==BX1 && dx < 0) /* object leaves playfield to the left */
649 else if (x==BX2 && dx > 0) /* object leaves playfield to the right */
651 else if (dx) /* general horizontal movement */
652 MarkTileDirty(x + SIGN(dx), y);
654 if (y < BY1) /* object enters playfield from the top */
656 if (cut_mode==CUT_BELOW) /* object completely above top border */
664 else if (y > BY2) /* object enters playfield from the bottom */
670 else if (y==BY1 && dy < 0) /* object leaves playfield to the top */
676 else if (dy > 0 && cut_mode == CUT_ABOVE)
678 if (y == BY2) /* object completely above bottom border */
684 MarkTileDirty(x, y + 1);
685 } /* object leaves playfield to the bottom */
686 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
688 else if (dy) /* general vertical movement */
689 MarkTileDirty(x, y + SIGN(dy));
693 if (!IN_SCR_FIELD(x, y))
695 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
696 printf("DrawGraphicShifted(): This should never happen!\n");
701 if (width > 0 && height > 0)
703 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
708 dst_x = FX + x * TILEX + dx;
709 dst_y = FY + y * TILEY + dy;
711 if (mask_mode == USE_MASKING)
713 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
714 dst_x - src_x, dst_y - src_y);
715 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
719 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
726 inline static void DrawGraphicShiftedDouble(int x, int y, int dx, int dy,
727 int graphic, int frame,
728 int cut_mode, int mask_mode)
733 int width = TILEX, height = TILEY;
736 int x2 = x + SIGN(dx);
737 int y2 = y + SIGN(dy);
738 int anim_frames = graphic_info[graphic].anim_frames;
739 int sync_frame = (dx ? ABS(dx) : ABS(dy)) * anim_frames / TILESIZE;
741 /* re-calculate animation frame for two-tile movement animation */
742 frame = getGraphicAnimationFrame(graphic, sync_frame);
744 if (IN_SCR_FIELD(x1, y1)) /* movement start graphic inside screen area */
746 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, TRUE);
748 dst_x = FX + x1 * TILEX;
749 dst_y = FY + y1 * TILEY;
751 if (mask_mode == USE_MASKING)
753 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
754 dst_x - src_x, dst_y - src_y);
755 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
759 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
762 MarkTileDirty(x1, y1);
765 if (IN_SCR_FIELD(x2, y2)) /* movement end graphic inside screen area */
767 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, FALSE);
769 dst_x = FX + x2 * TILEX;
770 dst_y = FY + y2 * TILEY;
772 if (mask_mode == USE_MASKING)
774 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
775 dst_x - src_x, dst_y - src_y);
776 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
780 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
783 MarkTileDirty(x2, y2);
787 static void DrawGraphicShifted(int x, int y, int dx, int dy,
788 int graphic, int frame,
789 int cut_mode, int mask_mode)
793 DrawGraphic(x, y, graphic, frame);
798 if (graphic_info[graphic].double_movement) /* EM style movement images */
799 DrawGraphicShiftedDouble(x, y, dx, dy, graphic, frame, cut_mode,mask_mode);
801 DrawGraphicShiftedNormal(x, y, dx, dy, graphic, frame, cut_mode,mask_mode);
804 void DrawGraphicShiftedThruMask(int x, int y, int dx, int dy, int graphic,
805 int frame, int cut_mode)
807 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, USE_MASKING);
810 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
811 int cut_mode, int mask_mode)
813 int lx = LEVELX(x), ly = LEVELY(y);
817 if (IN_LEV_FIELD(lx, ly))
819 SetRandomAnimationValue(lx, ly);
821 graphic = el_act_dir2img(element, GfxAction[lx][ly], GfxDir[lx][ly]);
822 frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
824 /* do not use double (EM style) movement graphic when not moving */
825 if (graphic_info[graphic].double_movement && !dx && !dy)
827 graphic = el_act_dir2img(element, ACTION_DEFAULT, GfxDir[lx][ly]);
828 frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
831 else /* border element */
833 graphic = el2img(element);
834 frame = getGraphicAnimationFrame(graphic, -1);
837 if (element == EL_EXPANDABLE_WALL)
839 boolean left_stopped = FALSE, right_stopped = FALSE;
841 if (!IN_LEV_FIELD(lx - 1, ly) || IS_WALL(Feld[lx - 1][ly]))
843 if (!IN_LEV_FIELD(lx + 1, ly) || IS_WALL(Feld[lx + 1][ly]))
844 right_stopped = TRUE;
846 if (left_stopped && right_stopped)
848 else if (left_stopped)
850 graphic = IMG_EXPANDABLE_WALL_GROWING_RIGHT;
851 frame = graphic_info[graphic].anim_frames - 1;
853 else if (right_stopped)
855 graphic = IMG_EXPANDABLE_WALL_GROWING_LEFT;
856 frame = graphic_info[graphic].anim_frames - 1;
861 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
862 else if (mask_mode == USE_MASKING)
863 DrawGraphicThruMask(x, y, graphic, frame);
865 DrawGraphic(x, y, graphic, frame);
868 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
869 int cut_mode, int mask_mode)
871 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
872 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
873 cut_mode, mask_mode);
876 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
879 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
882 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
885 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
888 void DrawLevelElementThruMask(int x, int y, int element)
890 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
893 void DrawLevelFieldThruMask(int x, int y)
895 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
898 #define TILE_GFX_ELEMENT(x, y) \
899 (GfxElement[x][y] != EL_UNDEFINED && Feld[x][y] != EL_EXPLOSION ? \
900 GfxElement[x][y] : Feld[x][y])
902 static void DrawLevelFieldCrumbledSandExt(int x, int y, int graphic, int frame)
906 int sx = SCREENX(x), sy = SCREENY(y);
908 int width, height, cx, cy, i;
909 int crumbled_border_size = graphic_info[graphic].border_size;
910 static int xy[4][2] =
918 if (!IN_LEV_FIELD(x, y))
921 element = TILE_GFX_ELEMENT(x, y);
923 /* crumble field itself */
924 if (GFX_CRUMBLED(element) && !IS_MOVING(x, y))
926 if (!IN_SCR_FIELD(sx, sy))
929 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
931 for (i = 0; i < 4; i++)
933 int xx = x + xy[i][0];
934 int yy = y + xy[i][1];
936 element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
939 /* check if neighbour field is of same type */
940 if (GFX_CRUMBLED(element) && !IS_MOVING(xx, yy))
943 if (i == 1 || i == 2)
945 width = crumbled_border_size;
947 cx = (i == 2 ? TILEX - crumbled_border_size : 0);
953 height = crumbled_border_size;
955 cy = (i == 3 ? TILEY - crumbled_border_size : 0);
958 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
959 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
962 MarkTileDirty(sx, sy);
964 else /* crumble neighbour fields */
966 for (i = 0; i < 4; i++)
968 int xx = x + xy[i][0];
969 int yy = y + xy[i][1];
970 int sxx = sx + xy[i][0];
971 int syy = sy + xy[i][1];
974 if (!IN_LEV_FIELD(xx, yy) ||
975 !IN_SCR_FIELD(sxx, syy) ||
979 element = TILE_GFX_ELEMENT(xx, yy);
981 if (!GFX_CRUMBLED(element))
984 if (!IN_LEV_FIELD(xx, yy) ||
985 !IN_SCR_FIELD(sxx, syy) ||
986 !GFX_CRUMBLED(Feld[xx][yy]) ||
991 graphic = el_act2crm(Feld[xx][yy], ACTION_DEFAULT);
992 crumbled_border_size = graphic_info[graphic].border_size;
994 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
996 if (i == 1 || i == 2)
998 width = crumbled_border_size;
1000 cx = (i == 1 ? TILEX - crumbled_border_size : 0);
1006 height = crumbled_border_size;
1008 cy = (i == 0 ? TILEY - crumbled_border_size : 0);
1011 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1012 width, height, FX + sxx * TILEX + cx, FY + syy * TILEY + cy);
1014 MarkTileDirty(sxx, syy);
1019 void DrawLevelFieldCrumbledSand(int x, int y)
1023 if (!IN_LEV_FIELD(x, y))
1026 graphic = el_act2crm(Feld[x][y], ACTION_DEFAULT);
1028 DrawLevelFieldCrumbledSandExt(x, y, graphic, 0);
1031 void DrawLevelFieldCrumbledSandDigging(int x, int y, int direction,
1034 int graphic1 = el_act_dir2img(GfxElement[x][y], ACTION_DIGGING, direction);
1035 int graphic2 = el_act_dir2crm(GfxElement[x][y], ACTION_DIGGING, direction);
1036 int frame1 = getGraphicAnimationFrame(graphic1, step_frame);
1037 int frame2 = getGraphicAnimationFrame(graphic2, step_frame);
1038 int sx = SCREENX(x), sy = SCREENY(y);
1040 DrawGraphic(sx, sy, graphic1, frame1);
1041 DrawLevelFieldCrumbledSandExt(x, y, graphic2, frame2);
1044 void DrawLevelFieldCrumbledSandNeighbours(int x, int y)
1046 int sx = SCREENX(x), sy = SCREENY(y);
1047 static int xy[4][2] =
1056 for (i = 0; i < 4; i++)
1058 int xx = x + xy[i][0];
1059 int yy = y + xy[i][1];
1060 int sxx = sx + xy[i][0];
1061 int syy = sy + xy[i][1];
1063 if (!IN_LEV_FIELD(xx, yy) ||
1064 !IN_SCR_FIELD(sxx, syy) ||
1065 !GFX_CRUMBLED(Feld[xx][yy]) ||
1069 DrawLevelField(xx, yy);
1073 static int getBorderElement(int x, int y)
1077 { EL_STEELWALL_TOPLEFT, EL_INVISIBLE_STEELWALL_TOPLEFT },
1078 { EL_STEELWALL_TOPRIGHT, EL_INVISIBLE_STEELWALL_TOPRIGHT },
1079 { EL_STEELWALL_BOTTOMLEFT, EL_INVISIBLE_STEELWALL_BOTTOMLEFT },
1080 { EL_STEELWALL_BOTTOMRIGHT, EL_INVISIBLE_STEELWALL_BOTTOMRIGHT },
1081 { EL_STEELWALL_VERTICAL, EL_INVISIBLE_STEELWALL_VERTICAL },
1082 { EL_STEELWALL_HORIZONTAL, EL_INVISIBLE_STEELWALL_HORIZONTAL },
1083 { EL_STEELWALL, EL_INVISIBLE_STEELWALL }
1085 int steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
1086 int steel_position = (x == -1 && y == -1 ? 0 :
1087 x == lev_fieldx && y == -1 ? 1 :
1088 x == -1 && y == lev_fieldy ? 2 :
1089 x == lev_fieldx && y == lev_fieldy ? 3 :
1090 x == -1 || x == lev_fieldx ? 4 :
1091 y == -1 || y == lev_fieldy ? 5 : 6);
1093 return border[steel_position][steel_type];
1096 void DrawScreenElement(int x, int y, int element)
1098 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1099 DrawLevelFieldCrumbledSand(LEVELX(x), LEVELY(y));
1102 void DrawLevelElement(int x, int y, int element)
1104 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1105 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1108 void DrawScreenField(int x, int y)
1110 int lx = LEVELX(x), ly = LEVELY(y);
1111 int element, content;
1113 if (!IN_LEV_FIELD(lx, ly))
1115 if (lx < -1 || lx > lev_fieldx || ly < -1 || ly > lev_fieldy)
1118 element = getBorderElement(lx, ly);
1120 DrawScreenElement(x, y, element);
1124 element = Feld[lx][ly];
1125 content = Store[lx][ly];
1127 if (IS_MOVING(lx, ly))
1129 int horiz_move = (MovDir[lx][ly] == MV_LEFT || MovDir[lx][ly] == MV_RIGHT);
1130 boolean cut_mode = NO_CUTTING;
1132 if (element == EL_QUICKSAND_EMPTYING ||
1133 element == EL_MAGIC_WALL_EMPTYING ||
1134 element == EL_BD_MAGIC_WALL_EMPTYING ||
1135 element == EL_AMOEBA_DROPPING)
1136 cut_mode = CUT_ABOVE;
1137 else if (element == EL_QUICKSAND_FILLING ||
1138 element == EL_MAGIC_WALL_FILLING ||
1139 element == EL_BD_MAGIC_WALL_FILLING)
1140 cut_mode = CUT_BELOW;
1142 if (cut_mode == CUT_ABOVE)
1143 DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1145 DrawScreenElement(x, y, EL_EMPTY);
1148 DrawScreenElementShifted(x, y, MovPos[lx][ly], 0, element, NO_CUTTING);
1149 else if (cut_mode == NO_CUTTING)
1150 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], element, cut_mode);
1152 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], content, cut_mode);
1154 if (content == EL_ACID)
1156 int dir = MovDir[lx][ly];
1157 int newlx = lx + (dir == MV_LEFT ? -1 : dir == MV_RIGHT ? +1 : 0);
1158 int newly = ly + (dir == MV_UP ? -1 : dir == MV_DOWN ? +1 : 0);
1160 DrawLevelElementThruMask(newlx, newly, EL_ACID);
1163 else if (IS_BLOCKED(lx, ly))
1168 boolean cut_mode = NO_CUTTING;
1169 int element_old, content_old;
1171 Blocked2Moving(lx, ly, &oldx, &oldy);
1174 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1175 MovDir[oldx][oldy] == MV_RIGHT);
1177 element_old = Feld[oldx][oldy];
1178 content_old = Store[oldx][oldy];
1180 if (element_old == EL_QUICKSAND_EMPTYING ||
1181 element_old == EL_MAGIC_WALL_EMPTYING ||
1182 element_old == EL_BD_MAGIC_WALL_EMPTYING ||
1183 element_old == EL_AMOEBA_DROPPING)
1184 cut_mode = CUT_ABOVE;
1186 DrawScreenElement(x, y, EL_EMPTY);
1189 DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
1191 else if (cut_mode == NO_CUTTING)
1192 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
1195 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
1198 else if (IS_DRAWABLE(element))
1199 DrawScreenElement(x, y, element);
1201 DrawScreenElement(x, y, EL_EMPTY);
1204 void DrawLevelField(int x, int y)
1206 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1207 DrawScreenField(SCREENX(x), SCREENY(y));
1208 else if (IS_MOVING(x, y))
1212 Moving2Blocked(x, y, &newx, &newy);
1213 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1214 DrawScreenField(SCREENX(newx), SCREENY(newy));
1216 else if (IS_BLOCKED(x, y))
1220 Blocked2Moving(x, y, &oldx, &oldy);
1221 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1222 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1226 void DrawMiniElement(int x, int y, int element)
1230 graphic = el2edimg(element);
1231 DrawMiniGraphic(x, y, graphic);
1234 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1236 int x = sx + scroll_x, y = sy + scroll_y;
1238 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1239 DrawMiniElement(sx, sy, EL_EMPTY);
1240 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1241 DrawMiniElement(sx, sy, Feld[x][y]);
1243 DrawMiniGraphic(sx, sy, el2edimg(getBorderElement(x, y)));
1246 void DrawEnvelopeBackground(int envelope_nr, int startx, int starty,
1247 int x, int y, int xsize, int ysize, int font_nr)
1249 int font_width = getFontWidth(font_nr);
1250 int font_height = getFontHeight(font_nr);
1251 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1254 int dst_x = SX + startx + x * font_width;
1255 int dst_y = SY + starty + y * font_height;
1256 int width = graphic_info[graphic].width;
1257 int height = graphic_info[graphic].height;
1258 int inner_width = MAX(width - 2 * font_width, font_width);
1259 int inner_height = MAX(height - 2 * font_height, font_height);
1260 int inner_sx = (width >= 3 * font_width ? font_width : 0);
1261 int inner_sy = (height >= 3 * font_height ? font_height : 0);
1262 boolean draw_masked = graphic_info[graphic].draw_masked;
1264 getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
1266 if (src_bitmap == NULL || width < font_width || height < font_height)
1268 ClearRectangle(drawto, dst_x, dst_y, font_width, font_height);
1272 src_x += (x == 0 ? 0 : x == xsize - 1 ? width - font_width :
1273 inner_sx + (x - 1) * font_width % inner_width);
1274 src_y += (y == 0 ? 0 : y == ysize - 1 ? height - font_height :
1275 inner_sy + (y - 1) * font_height % inner_height);
1279 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1280 dst_x - src_x, dst_y - src_y);
1281 BlitBitmapMasked(src_bitmap, drawto, src_x, src_y, font_width, font_height,
1285 BlitBitmap(src_bitmap, drawto, src_x, src_y, font_width, font_height,
1289 void AnimateEnvelope(int envelope_nr, int anim_mode, int action)
1291 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1292 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
1293 int mask_mode = (src_bitmap != NULL ? BLIT_MASKED : BLIT_ON_BACKGROUND);
1294 boolean ffwd_delay = (tape.playing && tape.fast_forward);
1295 boolean no_delay = (tape.warp_forward);
1296 unsigned long anim_delay = 0;
1297 int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
1298 int anim_delay_value = (no_delay ? 0 : frame_delay_value);
1299 int font_nr = FONT_ENVELOPE_1 + envelope_nr;
1300 int font_width = getFontWidth(font_nr);
1301 int font_height = getFontHeight(font_nr);
1302 int max_xsize = level.envelope_xsize[envelope_nr];
1303 int max_ysize = level.envelope_ysize[envelope_nr];
1304 int xstart = (anim_mode & ANIM_VERTICAL ? max_xsize : 0);
1305 int ystart = (anim_mode & ANIM_HORIZONTAL ? max_ysize : 0);
1306 int xend = max_xsize;
1307 int yend = (anim_mode != ANIM_DEFAULT ? max_ysize : 0);
1308 int xstep = (xstart < xend ? 1 : 0);
1309 int ystep = (ystart < yend || xstep == 0 ? 1 : 0);
1312 for (x = xstart, y = ystart; x <= xend && y <= yend; x += xstep, y += ystep)
1314 int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2;
1315 int ysize = (action == ACTION_CLOSING ? yend - (y - ystart) : y) + 2;
1316 int sx = (SXSIZE - xsize * font_width) / 2;
1317 int sy = (SYSIZE - ysize * font_height) / 2;
1320 SetDrawtoField(DRAW_BUFFERED);
1322 BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
1324 SetDrawtoField(DRAW_BACKBUFFER);
1326 for (yy = 0; yy < ysize; yy++) for (xx = 0; xx < xsize; xx++)
1327 DrawEnvelopeBackground(envelope_nr, sx,sy, xx,yy, xsize, ysize, font_nr);
1329 DrawTextToTextArea(SX + sx + font_width, SY + sy + font_height,
1330 level.envelope_text[envelope_nr], font_nr, max_xsize,
1331 xsize - 2, ysize - 2, mask_mode);
1333 redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
1336 WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
1340 void ShowEnvelope(int envelope_nr)
1342 int element = EL_ENVELOPE_1 + envelope_nr;
1343 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1344 int sound_opening = element_info[element].sound[ACTION_OPENING];
1345 int sound_closing = element_info[element].sound[ACTION_CLOSING];
1346 boolean ffwd_delay = (tape.playing && tape.fast_forward);
1347 boolean no_delay = (tape.warp_forward);
1348 int normal_delay_value = ONE_SECOND_DELAY / (ffwd_delay ? 2 : 1);
1349 int wait_delay_value = (no_delay ? 0 : normal_delay_value);
1350 int anim_mode = graphic_info[graphic].anim_mode;
1351 int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL:
1352 anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode);
1354 game.envelope_active = TRUE; /* needed for RedrawPlayfield() events */
1356 PlaySoundStereo(sound_opening, SOUND_MIDDLE);
1358 if (anim_mode == ANIM_DEFAULT)
1359 AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_OPENING);
1361 AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_OPENING);
1364 Delay(wait_delay_value);
1366 WaitForEventToContinue();
1368 PlaySoundStereo(sound_closing, SOUND_MIDDLE);
1370 if (anim_mode != ANIM_NONE)
1371 AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_CLOSING);
1373 if (anim_mode == ANIM_DEFAULT)
1374 AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_CLOSING);
1376 game.envelope_active = FALSE;
1378 SetDrawtoField(DRAW_BUFFERED);
1380 redraw_mask |= REDRAW_FIELD;
1384 void getMicroGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1386 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
1387 int mini_startx = src_bitmap->width * 3 / 4;
1388 int mini_starty = src_bitmap->height * 2 / 3;
1389 int src_x = mini_startx + graphic_info[graphic].src_x / 8;
1390 int src_y = mini_starty + graphic_info[graphic].src_y / 8;
1392 *bitmap = src_bitmap;
1397 void DrawMicroElement(int xpos, int ypos, int element)
1401 int graphic = el2preimg(element);
1403 getMicroGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1404 BlitBitmap(src_bitmap, drawto, src_x, src_y, MICRO_TILEX, MICRO_TILEY,
1412 SetDrawBackgroundMask(REDRAW_NONE);
1415 for (x = BX1; x <= BX2; x++)
1416 for (y = BY1; y <= BY2; y++)
1417 DrawScreenField(x, y);
1419 redraw_mask |= REDRAW_FIELD;
1422 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1426 for (x = 0; x < size_x; x++)
1427 for (y = 0; y < size_y; y++)
1428 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1430 redraw_mask |= REDRAW_FIELD;
1433 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1437 DrawBackground(xpos, ypos, MICROLEVEL_XSIZE, MICROLEVEL_YSIZE);
1439 if (lev_fieldx < STD_LEV_FIELDX)
1440 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1441 if (lev_fieldy < STD_LEV_FIELDY)
1442 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1444 xpos += MICRO_TILEX;
1445 ypos += MICRO_TILEY;
1447 for (x = -1; x <= STD_LEV_FIELDX; x++)
1449 for (y = -1; y <= STD_LEV_FIELDY; y++)
1451 int lx = from_x + x, ly = from_y + y;
1453 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1454 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1455 level.field[lx][ly]);
1456 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1
1457 && BorderElement != EL_EMPTY)
1458 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1459 getBorderElement(lx, ly));
1463 redraw_mask |= REDRAW_MICROLEVEL;
1466 #define MICROLABEL_EMPTY 0
1467 #define MICROLABEL_LEVEL_NAME 1
1468 #define MICROLABEL_LEVEL_AUTHOR_HEAD 2
1469 #define MICROLABEL_LEVEL_AUTHOR 3
1470 #define MICROLABEL_IMPORTED_FROM_HEAD 4
1471 #define MICROLABEL_IMPORTED_FROM 5
1472 #define MICROLABEL_IMPORTED_BY_HEAD 6
1473 #define MICROLABEL_IMPORTED_BY 7
1475 static void DrawMicroLevelLabelExt(int mode)
1477 char label_text[MAX_OUTPUT_LINESIZE + 1];
1478 int max_len_label_text;
1479 int font_nr = FONT_TEXT_2;
1482 if (mode == MICROLABEL_LEVEL_AUTHOR_HEAD ||
1483 mode == MICROLABEL_IMPORTED_FROM_HEAD ||
1484 mode == MICROLABEL_IMPORTED_BY_HEAD)
1485 font_nr = FONT_TEXT_3;
1487 max_len_label_text = SXSIZE / getFontWidth(font_nr);
1489 for (i = 0; i < max_len_label_text; i++)
1490 label_text[i] = ' ';
1491 label_text[max_len_label_text] = '\0';
1493 if (strlen(label_text) > 0)
1495 int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
1496 int lypos = MICROLABEL2_YPOS;
1498 DrawText(lxpos, lypos, label_text, font_nr);
1502 (mode == MICROLABEL_LEVEL_NAME ? level.name :
1503 mode == MICROLABEL_LEVEL_AUTHOR_HEAD ? "created by" :
1504 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
1505 mode == MICROLABEL_IMPORTED_FROM_HEAD ? "imported from" :
1506 mode == MICROLABEL_IMPORTED_FROM ? leveldir_current->imported_from :
1507 mode == MICROLABEL_IMPORTED_BY_HEAD ? "imported by" :
1508 mode == MICROLABEL_IMPORTED_BY ? leveldir_current->imported_by :""),
1509 max_len_label_text);
1510 label_text[max_len_label_text] = '\0';
1512 if (strlen(label_text) > 0)
1514 int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
1515 int lypos = MICROLABEL2_YPOS;
1517 DrawText(lxpos, lypos, label_text, font_nr);
1520 redraw_mask |= REDRAW_MICROLEVEL;
1523 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1525 static unsigned long scroll_delay = 0;
1526 static unsigned long label_delay = 0;
1527 static int from_x, from_y, scroll_direction;
1528 static int label_state, label_counter;
1529 int last_game_status = game_status; /* save current game status */
1531 /* force PREVIEW font on preview level */
1532 game_status = GAME_MODE_PSEUDO_PREVIEW;
1536 from_x = from_y = 0;
1537 scroll_direction = MV_RIGHT;
1541 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1542 DrawMicroLevelLabelExt(label_state);
1544 /* initialize delay counters */
1545 DelayReached(&scroll_delay, 0);
1546 DelayReached(&label_delay, 0);
1548 if (leveldir_current->name)
1550 char label_text[MAX_OUTPUT_LINESIZE + 1];
1551 int font_nr = FONT_TEXT_1;
1552 int max_len_label_text = SXSIZE / getFontWidth(font_nr);
1555 strncpy(label_text, leveldir_current->name, max_len_label_text);
1556 label_text[max_len_label_text] = '\0';
1558 lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
1559 lypos = SY + MICROLABEL1_YPOS;
1561 DrawText(lxpos, lypos, label_text, font_nr);
1564 game_status = last_game_status; /* restore current game status */
1569 /* scroll micro level, if needed */
1570 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1571 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1573 switch (scroll_direction)
1579 scroll_direction = MV_UP;
1583 if (from_x < lev_fieldx - STD_LEV_FIELDX)
1586 scroll_direction = MV_DOWN;
1593 scroll_direction = MV_RIGHT;
1597 if (from_y < lev_fieldy - STD_LEV_FIELDY)
1600 scroll_direction = MV_LEFT;
1607 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1610 /* !!! THIS ALL SUCKS -- SHOULD BE CLEANLY REWRITTEN !!! */
1611 /* redraw micro level label, if needed */
1612 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1613 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1614 strcmp(level.author, leveldir_current->name) != 0 &&
1615 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1617 int max_label_counter = 23;
1619 if (leveldir_current->imported_from != NULL &&
1620 strlen(leveldir_current->imported_from) > 0)
1621 max_label_counter += 14;
1622 if (leveldir_current->imported_by != NULL &&
1623 strlen(leveldir_current->imported_by) > 0)
1624 max_label_counter += 14;
1626 label_counter = (label_counter + 1) % max_label_counter;
1627 label_state = (label_counter >= 0 && label_counter <= 7 ?
1628 MICROLABEL_LEVEL_NAME :
1629 label_counter >= 9 && label_counter <= 12 ?
1630 MICROLABEL_LEVEL_AUTHOR_HEAD :
1631 label_counter >= 14 && label_counter <= 21 ?
1632 MICROLABEL_LEVEL_AUTHOR :
1633 label_counter >= 23 && label_counter <= 26 ?
1634 MICROLABEL_IMPORTED_FROM_HEAD :
1635 label_counter >= 28 && label_counter <= 35 ?
1636 MICROLABEL_IMPORTED_FROM :
1637 label_counter >= 37 && label_counter <= 40 ?
1638 MICROLABEL_IMPORTED_BY_HEAD :
1639 label_counter >= 42 && label_counter <= 49 ?
1640 MICROLABEL_IMPORTED_BY : MICROLABEL_EMPTY);
1642 if (leveldir_current->imported_from == NULL &&
1643 (label_state == MICROLABEL_IMPORTED_FROM_HEAD ||
1644 label_state == MICROLABEL_IMPORTED_FROM))
1645 label_state = (label_state == MICROLABEL_IMPORTED_FROM_HEAD ?
1646 MICROLABEL_IMPORTED_BY_HEAD : MICROLABEL_IMPORTED_BY);
1648 DrawMicroLevelLabelExt(label_state);
1651 game_status = last_game_status; /* restore current game status */
1654 inline void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
1655 int graphic, int sync_frame, int mask_mode)
1657 int frame = getGraphicAnimationFrame(graphic, sync_frame);
1659 if (mask_mode == USE_MASKING)
1660 DrawGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
1662 DrawGraphicExt(dst_bitmap, x, y, graphic, frame);
1665 inline void DrawGraphicAnimation(int x, int y, int graphic)
1667 int lx = LEVELX(x), ly = LEVELY(y);
1669 if (!IN_SCR_FIELD(x, y))
1672 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
1673 graphic, GfxFrame[lx][ly], NO_MASKING);
1674 MarkTileDirty(x, y);
1677 void DrawLevelGraphicAnimation(int x, int y, int graphic)
1679 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
1682 void DrawLevelElementAnimation(int x, int y, int element)
1684 int graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
1686 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
1689 inline void DrawLevelGraphicAnimationIfNeeded(int x, int y, int graphic)
1691 int sx = SCREENX(x), sy = SCREENY(y);
1693 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
1696 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
1699 DrawGraphicAnimation(sx, sy, graphic);
1701 if (GFX_CRUMBLED(Feld[x][y]))
1702 DrawLevelFieldCrumbledSand(x, y);
1705 void DrawLevelElementAnimationIfNeeded(int x, int y, int element)
1707 int sx = SCREENX(x), sy = SCREENY(y);
1710 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
1713 graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
1715 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
1718 DrawGraphicAnimation(sx, sy, graphic);
1720 if (GFX_CRUMBLED(element))
1721 DrawLevelFieldCrumbledSand(x, y);
1724 static int getPlayerGraphic(struct PlayerInfo *player, int move_dir)
1726 if (player->use_murphy_graphic)
1728 /* this works only because currently only one player can be "murphy" ... */
1729 static int last_horizontal_dir = MV_LEFT;
1730 int graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, move_dir);
1732 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
1733 last_horizontal_dir = move_dir;
1735 if (graphic == IMG_SP_MURPHY) /* undefined => use special graphic */
1737 int direction = (player->is_snapping ? move_dir : last_horizontal_dir);
1739 graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, direction);
1745 return el_act_dir2img(player->element_nr, player->GfxAction, move_dir);
1748 static boolean equalGraphics(int graphic1, int graphic2)
1750 struct GraphicInfo *g1 = &graphic_info[graphic1];
1751 struct GraphicInfo *g2 = &graphic_info[graphic2];
1753 return (g1->bitmap == g2->bitmap &&
1754 g1->src_x == g2->src_x &&
1755 g1->src_y == g2->src_y &&
1756 g1->anim_frames == g2->anim_frames &&
1757 g1->anim_delay == g2->anim_delay &&
1758 g1->anim_mode == g2->anim_mode);
1761 void DrawAllPlayers()
1765 for (i = 0; i < MAX_PLAYERS; i++)
1766 if (stored_player[i].active)
1767 DrawPlayer(&stored_player[i]);
1770 void DrawPlayerField(int x, int y)
1772 if (!IS_PLAYER(x, y))
1775 DrawPlayer(PLAYERINFO(x, y));
1778 void DrawPlayer(struct PlayerInfo *player)
1780 int jx = player->jx;
1781 int jy = player->jy;
1782 int move_dir = player->MovDir;
1783 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? +1 : 0);
1784 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? +1 : 0);
1785 int last_jx = (player->is_moving ? jx - dx : jx);
1786 int last_jy = (player->is_moving ? jy - dy : jy);
1787 int next_jx = jx + dx;
1788 int next_jy = jy + dy;
1789 boolean player_is_moving = (player->MovPos ? TRUE : FALSE);
1790 int sx = SCREENX(jx), sy = SCREENY(jy);
1791 int sxx = 0, syy = 0;
1792 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
1794 int action = ACTION_DEFAULT;
1795 int last_player_graphic = getPlayerGraphic(player, move_dir);
1796 int last_player_frame = player->Frame;
1799 if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
1803 if (!IN_LEV_FIELD(jx, jy))
1805 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
1806 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
1807 printf("DrawPlayerField(): This should never happen!\n");
1812 if (element == EL_EXPLOSION)
1815 action = (player->is_pushing ? ACTION_PUSHING :
1816 player->is_digging ? ACTION_DIGGING :
1817 player->is_collecting ? ACTION_COLLECTING :
1818 player->is_moving ? ACTION_MOVING :
1819 player->is_snapping ? ACTION_SNAPPING :
1820 player->is_dropping ? ACTION_DROPPING :
1821 player->is_waiting ? player->action_waiting : ACTION_DEFAULT);
1823 InitPlayerGfxAnimation(player, action, move_dir);
1825 /* ----------------------------------------------------------------------- */
1826 /* draw things in the field the player is leaving, if needed */
1827 /* ----------------------------------------------------------------------- */
1829 if (player->is_moving)
1831 if (Back[last_jx][last_jy] && IS_DRAWABLE(last_element))
1833 DrawLevelElement(last_jx, last_jy, Back[last_jx][last_jy]);
1835 if (last_element == EL_DYNAMITE_ACTIVE ||
1836 last_element == EL_SP_DISK_RED_ACTIVE)
1837 DrawDynamite(last_jx, last_jy);
1839 DrawLevelFieldThruMask(last_jx, last_jy);
1841 else if (last_element == EL_DYNAMITE_ACTIVE ||
1842 last_element == EL_SP_DISK_RED_ACTIVE)
1843 DrawDynamite(last_jx, last_jy);
1845 DrawLevelField(last_jx, last_jy);
1847 if (player->is_pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
1848 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
1851 if (!IN_SCR_FIELD(sx, sy))
1854 if (setup.direct_draw)
1855 SetDrawtoField(DRAW_BUFFERED);
1857 /* ----------------------------------------------------------------------- */
1858 /* draw things behind the player, if needed */
1859 /* ----------------------------------------------------------------------- */
1862 DrawLevelElement(jx, jy, Back[jx][jy]);
1863 else if (IS_ACTIVE_BOMB(element))
1864 DrawLevelElement(jx, jy, EL_EMPTY);
1867 if (player_is_moving && GfxElement[jx][jy] != EL_UNDEFINED)
1869 if (GFX_CRUMBLED(GfxElement[jx][jy]))
1870 DrawLevelFieldCrumbledSandDigging(jx, jy, move_dir, player->StepFrame);
1873 int old_element = GfxElement[jx][jy];
1874 int old_graphic = el_act_dir2img(old_element, action, move_dir);
1875 int frame = getGraphicAnimationFrame(old_graphic, player->StepFrame);
1877 DrawGraphic(sx, sy, old_graphic, frame);
1882 GfxElement[jx][jy] = EL_UNDEFINED;
1884 DrawLevelField(jx, jy);
1888 /* ----------------------------------------------------------------------- */
1889 /* draw player himself */
1890 /* ----------------------------------------------------------------------- */
1892 graphic = getPlayerGraphic(player, move_dir);
1894 /* in the case of changed player action or direction, prevent the current
1895 animation frame from being restarted for identical animations */
1896 if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic))
1897 player->Frame = last_player_frame;
1899 frame = getGraphicAnimationFrame(graphic, player->Frame);
1903 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
1904 sxx = player->GfxPos;
1906 syy = player->GfxPos;
1909 if (!setup.soft_scrolling && ScreenMovPos)
1912 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
1914 if (SHIELD_ON(player))
1916 int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
1917 IMG_SHIELD_NORMAL_ACTIVE);
1918 int frame = getGraphicAnimationFrame(graphic, -1);
1920 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
1923 /* ----------------------------------------------------------------------- */
1924 /* draw things the player is pushing, if needed */
1925 /* ----------------------------------------------------------------------- */
1928 printf("::: %d, %d [%d, %d] [%d]\n",
1929 player->is_pushing, player_is_moving, player->GfxAction,
1930 player->is_moving, player_is_moving);
1933 if (player->is_pushing && player->is_moving)
1935 int px = SCREENX(jx), py = SCREENY(jy);
1936 int pxx = (TILEX - ABS(sxx)) * dx;
1937 int pyy = (TILEY - ABS(syy)) * dy;
1942 if (!IS_MOVING(jx, jy)) /* push movement already finished */
1943 element = Feld[next_jx][next_jy];
1945 graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
1946 frame = getGraphicAnimationFrame(graphic, player->StepFrame);
1948 /* draw background element under pushed element (like the Sokoban field) */
1949 if (Back[next_jx][next_jy])
1950 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
1952 /* masked drawing is needed for EMC style (double) movement graphics */
1953 DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame, NO_CUTTING);
1956 /* ----------------------------------------------------------------------- */
1957 /* draw things in front of player (active dynamite or dynabombs) */
1958 /* ----------------------------------------------------------------------- */
1960 if (IS_ACTIVE_BOMB(element))
1962 graphic = el2img(element);
1963 frame = getGraphicAnimationFrame(graphic, GfxFrame[jx][jy]);
1965 if (game.emulation == EMU_SUPAPLEX)
1966 DrawGraphic(sx, sy, IMG_SP_DISK_RED, frame);
1968 DrawGraphicThruMask(sx, sy, graphic, frame);
1971 if (player_is_moving && last_element == EL_EXPLOSION)
1973 int graphic = el_act2img(GfxElement[last_jx][last_jy], ACTION_EXPLODING);
1974 int delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2);
1975 int phase = ExplodePhase[last_jx][last_jy] - 1;
1976 int frame = getGraphicAnimationFrame(graphic, phase - delay);
1979 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy), graphic, frame);
1982 /* ----------------------------------------------------------------------- */
1983 /* draw elements the player is just walking/passing through/under */
1984 /* ----------------------------------------------------------------------- */
1986 if (player_is_moving)
1988 /* handle the field the player is leaving ... */
1989 if (IS_ACCESSIBLE_INSIDE(last_element))
1990 DrawLevelField(last_jx, last_jy);
1991 else if (IS_ACCESSIBLE_UNDER(last_element))
1992 DrawLevelFieldThruMask(last_jx, last_jy);
1995 /* do not redraw accessible elements if the player is just pushing them */
1996 if (!player_is_moving || !player->is_pushing)
1998 /* ... and the field the player is entering */
1999 if (IS_ACCESSIBLE_INSIDE(element))
2000 DrawLevelField(jx, jy);
2001 else if (IS_ACCESSIBLE_UNDER(element))
2002 DrawLevelFieldThruMask(jx, jy);
2005 if (setup.direct_draw)
2007 int dst_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
2008 int dst_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
2009 int x_size = TILEX * (1 + ABS(jx - last_jx));
2010 int y_size = TILEY * (1 + ABS(jy - last_jy));
2012 BlitBitmap(drawto_field, window,
2013 dst_x, dst_y, x_size, y_size, dst_x, dst_y);
2014 SetDrawtoField(DRAW_DIRECT);
2017 MarkTileDirty(sx, sy);
2020 /* ------------------------------------------------------------------------- */
2022 void WaitForEventToContinue()
2024 boolean still_wait = TRUE;
2026 /* simulate releasing mouse button over last gadget, if still pressed */
2028 HandleGadgets(-1, -1, 0);
2030 button_status = MB_RELEASED;
2042 case EVENT_BUTTONPRESS:
2043 case EVENT_KEYPRESS:
2047 case EVENT_KEYRELEASE:
2048 ClearPlayerAction();
2052 HandleOtherEvents(&event);
2056 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2063 /* don't eat all CPU time */
2068 #define MAX_REQUEST_LINES 13
2069 #define MAX_REQUEST_LINE_FONT1_LEN 7
2070 #define MAX_REQUEST_LINE_FONT2_LEN 10
2072 boolean Request(char *text, unsigned int req_state)
2074 int mx, my, ty, result = -1;
2075 unsigned int old_door_state;
2076 int last_game_status = game_status; /* save current game status */
2077 int max_request_line_len = MAX_REQUEST_LINE_FONT1_LEN;
2078 int font_nr = FONT_TEXT_2;
2079 int max_word_len = 0;
2082 for (text_ptr = text; *text_ptr; text_ptr++)
2084 max_word_len = (*text_ptr != ' ' ? max_word_len + 1 : 0);
2086 if (max_word_len > MAX_REQUEST_LINE_FONT1_LEN)
2088 max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
2089 font_nr = FONT_LEVEL_NUMBER;
2095 if (game_status == GAME_MODE_PLAYING &&
2096 level.game_engine_type == GAME_ENGINE_TYPE_EM)
2097 BlitScreenToBitmap_EM(backbuffer);
2099 /* disable deactivated drawing when quick-loading level tape recording */
2100 if (tape.playing && tape.deactivate_display)
2101 TapeDeactivateDisplayOff(TRUE);
2103 SetMouseCursor(CURSOR_DEFAULT);
2105 #if defined(NETWORK_AVALIABLE)
2106 /* pause network game while waiting for request to answer */
2107 if (options.network &&
2108 game_status == GAME_MODE_PLAYING &&
2109 req_state & REQUEST_WAIT_FOR_INPUT)
2110 SendToServer_PausePlaying();
2113 old_door_state = GetDoorState();
2115 /* simulate releasing mouse button over last gadget, if still pressed */
2117 HandleGadgets(-1, -1, 0);
2121 if (old_door_state & DOOR_OPEN_1)
2123 CloseDoor(DOOR_CLOSE_1);
2125 /* save old door content */
2126 BlitBitmap(bitmap_db_door, bitmap_db_door,
2127 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
2128 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
2131 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
2133 /* clear door drawing field */
2134 DrawBackground(DX, DY, DXSIZE, DYSIZE);
2136 /* force DOOR font on preview level */
2137 game_status = GAME_MODE_PSEUDO_DOOR;
2139 /* write text for request */
2140 for (ty = 0; ty < MAX_REQUEST_LINES; ty++)
2142 char text_line[max_request_line_len + 1];
2148 for (tl = 0, tx = 0; tx < max_request_line_len; tl++, tx++)
2151 if (!tc || tc == ' ')
2162 strncpy(text_line, text, tl);
2165 DrawText(DX + (DXSIZE - tl * getFontWidth(font_nr)) / 2,
2166 DY + 8 + ty * (getFontHeight(font_nr) + 2),
2167 text_line, font_nr);
2169 text += tl + (tc == ' ' ? 1 : 0);
2172 game_status = last_game_status; /* restore current game status */
2174 if (req_state & REQ_ASK)
2176 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
2177 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
2179 else if (req_state & REQ_CONFIRM)
2181 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
2183 else if (req_state & REQ_PLAYER)
2185 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
2186 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
2187 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
2188 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
2191 /* copy request gadgets to door backbuffer */
2192 BlitBitmap(drawto, bitmap_db_door,
2193 DX, DY, DXSIZE, DYSIZE,
2194 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2196 OpenDoor(DOOR_OPEN_1);
2198 if (!(req_state & REQUEST_WAIT_FOR_INPUT))
2200 SetDrawBackgroundMask(REDRAW_FIELD);
2205 if (game_status != GAME_MODE_MAIN)
2208 button_status = MB_RELEASED;
2210 request_gadget_id = -1;
2212 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
2224 case EVENT_BUTTONPRESS:
2225 case EVENT_BUTTONRELEASE:
2226 case EVENT_MOTIONNOTIFY:
2228 if (event.type == EVENT_MOTIONNOTIFY)
2230 if (!PointerInWindow(window))
2231 continue; /* window and pointer are on different screens */
2236 motion_status = TRUE;
2237 mx = ((MotionEvent *) &event)->x;
2238 my = ((MotionEvent *) &event)->y;
2242 motion_status = FALSE;
2243 mx = ((ButtonEvent *) &event)->x;
2244 my = ((ButtonEvent *) &event)->y;
2245 if (event.type == EVENT_BUTTONPRESS)
2246 button_status = ((ButtonEvent *) &event)->button;
2248 button_status = MB_RELEASED;
2251 /* this sets 'request_gadget_id' */
2252 HandleGadgets(mx, my, button_status);
2254 switch(request_gadget_id)
2256 case TOOL_CTRL_ID_YES:
2259 case TOOL_CTRL_ID_NO:
2262 case TOOL_CTRL_ID_CONFIRM:
2263 result = TRUE | FALSE;
2266 case TOOL_CTRL_ID_PLAYER_1:
2269 case TOOL_CTRL_ID_PLAYER_2:
2272 case TOOL_CTRL_ID_PLAYER_3:
2275 case TOOL_CTRL_ID_PLAYER_4:
2286 case EVENT_KEYPRESS:
2287 switch(GetEventKey((KeyEvent *)&event, TRUE))
2300 if (req_state & REQ_PLAYER)
2304 case EVENT_KEYRELEASE:
2305 ClearPlayerAction();
2309 HandleOtherEvents(&event);
2313 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2315 int joy = AnyJoystick();
2317 if (joy & JOY_BUTTON_1)
2319 else if (joy & JOY_BUTTON_2)
2325 /* don't eat all CPU time */
2329 if (game_status != GAME_MODE_MAIN)
2334 if (!(req_state & REQ_STAY_OPEN))
2336 CloseDoor(DOOR_CLOSE_1);
2338 if (((old_door_state & DOOR_OPEN_1) && !(req_state & REQ_STAY_CLOSED)) ||
2339 (req_state & REQ_REOPEN))
2340 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
2345 SetDrawBackgroundMask(REDRAW_FIELD);
2347 #if defined(NETWORK_AVALIABLE)
2348 /* continue network game after request */
2349 if (options.network &&
2350 game_status == GAME_MODE_PLAYING &&
2351 req_state & REQUEST_WAIT_FOR_INPUT)
2352 SendToServer_ContinuePlaying();
2355 /* restore deactivated drawing when quick-loading level tape recording */
2356 if (tape.playing && tape.deactivate_display)
2357 TapeDeactivateDisplayOn();
2362 unsigned int OpenDoor(unsigned int door_state)
2364 if (door_state & DOOR_COPY_BACK)
2366 if (door_state & DOOR_OPEN_1)
2367 BlitBitmap(bitmap_db_door, bitmap_db_door,
2368 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
2369 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2371 if (door_state & DOOR_OPEN_2)
2372 BlitBitmap(bitmap_db_door, bitmap_db_door,
2373 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY2, VXSIZE, VYSIZE,
2374 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2376 door_state &= ~DOOR_COPY_BACK;
2379 return MoveDoor(door_state);
2382 unsigned int CloseDoor(unsigned int door_state)
2384 unsigned int old_door_state = GetDoorState();
2386 if (!(door_state & DOOR_NO_COPY_BACK))
2388 if (old_door_state & DOOR_OPEN_1)
2389 BlitBitmap(backbuffer, bitmap_db_door,
2390 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2392 if (old_door_state & DOOR_OPEN_2)
2393 BlitBitmap(backbuffer, bitmap_db_door,
2394 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2396 door_state &= ~DOOR_NO_COPY_BACK;
2399 return MoveDoor(door_state);
2402 unsigned int GetDoorState()
2404 return MoveDoor(DOOR_GET_STATE);
2407 unsigned int SetDoorState(unsigned int door_state)
2409 return MoveDoor(door_state | DOOR_SET_STATE);
2412 unsigned int MoveDoor(unsigned int door_state)
2414 static int door1 = DOOR_OPEN_1;
2415 static int door2 = DOOR_CLOSE_2;
2416 unsigned long door_delay = 0;
2417 unsigned long door_delay_value;
2420 if (door_state == DOOR_GET_STATE)
2421 return(door1 | door2);
2423 if (door_state & DOOR_SET_STATE)
2425 if (door_state & DOOR_ACTION_1)
2426 door1 = door_state & DOOR_ACTION_1;
2427 if (door_state & DOOR_ACTION_2)
2428 door2 = door_state & DOOR_ACTION_2;
2430 return(door1 | door2);
2433 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2434 door_state &= ~DOOR_OPEN_1;
2435 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2436 door_state &= ~DOOR_CLOSE_1;
2437 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2438 door_state &= ~DOOR_OPEN_2;
2439 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2440 door_state &= ~DOOR_CLOSE_2;
2442 door_delay_value = (door_state & DOOR_ACTION_1 ? door_1.step_delay :
2445 if (setup.quick_doors)
2447 stepsize = 20; /* must be choosen to always draw last frame */
2448 door_delay_value = 0;
2451 if (global.autoplay_leveldir)
2453 door_state |= DOOR_NO_DELAY;
2454 door_state &= ~DOOR_CLOSE_ALL;
2457 if (door_state & DOOR_ACTION)
2459 boolean door_1_done = !(door_state & DOOR_ACTION_1);
2460 boolean door_2_done = !(door_state & DOOR_ACTION_2);
2461 int start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2462 int end = (door_state & DOOR_ACTION_1 &&
2463 door_1.anim_mode == ANIM_VERTICAL ? DYSIZE : DXSIZE);
2466 if (!(door_state & DOOR_NO_DELAY) && !setup.quick_doors)
2468 /* opening door sound has priority over simultaneously closing door */
2469 if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
2470 PlaySoundStereo(SND_DOOR_OPENING, SOUND_MIDDLE);
2471 else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
2472 PlaySoundStereo(SND_DOOR_CLOSING, SOUND_MIDDLE);
2475 for (x = start; x <= end && !(door_1_done && door_2_done); x += stepsize)
2477 Bitmap *bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2478 GC gc = bitmap->stored_clip_gc;
2480 if (door_state & DOOR_ACTION_1)
2482 int a = MIN(x * door_1.step_offset, end);
2483 int i = (door_state & DOOR_OPEN_1 ? end - a : a);
2487 BlitBitmap(bitmap_db_door, drawto,
2488 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i / 2,
2489 DXSIZE, DYSIZE - i / 2, DX, DY);
2491 ClearRectangle(drawto, DX, DY + DYSIZE - i / 2, DXSIZE, i / 2);
2494 if (door_1.anim_mode == ANIM_HORIZONTAL && x <= DXSIZE)
2496 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
2497 int dst1_x = DX + DXSIZE - i, dst1_y = DY;
2498 int src2_x = DXSIZE - i, src2_y = DOOR_GFX_PAGEY1;
2499 int dst2_x = DX, dst2_y = DY;
2500 int width = i, height = DYSIZE;
2502 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2503 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2506 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2507 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2510 else if (door_1.anim_mode == ANIM_VERTICAL && x <= DYSIZE)
2512 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
2513 int dst1_x = DX, dst1_y = DY + DYSIZE - i;
2514 int src2_x = 0, src2_y = DOOR_GFX_PAGEY1 + DYSIZE - i;
2515 int dst2_x = DX, dst2_y = DY;
2516 int width = DXSIZE, height = i;
2518 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2519 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2522 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2523 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2526 else if (x <= DXSIZE) /* ANIM_DEFAULT */
2528 int j = (door_1.anim_mode == ANIM_DEFAULT ? (DXSIZE - i) / 3 : 0);
2530 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2531 BlitBitmapMasked(bitmap, drawto,
2532 DXSIZE, DOOR_GFX_PAGEY1, i, 77,
2533 DX + DXSIZE - i, DY + j);
2534 BlitBitmapMasked(bitmap, drawto,
2535 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
2536 DX + DXSIZE - i, DY + 140 + j);
2537 SetClipOrigin(bitmap, gc, DX - DXSIZE + i,
2538 DY - (DOOR_GFX_PAGEY1 + j));
2539 BlitBitmapMasked(bitmap, drawto,
2540 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
2542 BlitBitmapMasked(bitmap, drawto,
2543 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
2546 BlitBitmapMasked(bitmap, drawto,
2547 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2549 BlitBitmapMasked(bitmap, drawto,
2550 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2552 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2553 BlitBitmapMasked(bitmap, drawto,
2554 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2555 DX + DXSIZE - i, DY + 77 + j);
2556 BlitBitmapMasked(bitmap, drawto,
2557 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2558 DX + DXSIZE - i, DY + 203 + j);
2561 redraw_mask |= REDRAW_DOOR_1;
2562 door_1_done = (a == end);
2565 if (door_state & DOOR_ACTION_2)
2567 int a = MIN(x * door_2.step_offset, VXSIZE);
2568 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - a : a);
2572 BlitBitmap(bitmap_db_door, drawto,
2573 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i / 2,
2574 VXSIZE, VYSIZE - i / 2, VX, VY);
2576 ClearRectangle(drawto, VX, VY + VYSIZE - i / 2, VXSIZE, i / 2);
2579 if (door_2.anim_mode == ANIM_HORIZONTAL && x <= VXSIZE)
2581 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
2582 int dst1_x = VX + VXSIZE - i, dst1_y = VY;
2583 int src2_x = VXSIZE - i, src2_y = DOOR_GFX_PAGEY2;
2584 int dst2_x = VX, dst2_y = VY;
2585 int width = i, height = VYSIZE;
2587 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2588 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2591 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2592 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2595 else if (door_2.anim_mode == ANIM_VERTICAL && x <= VYSIZE)
2597 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
2598 int dst1_x = VX, dst1_y = VY + VYSIZE - i;
2599 int src2_x = 0, src2_y = DOOR_GFX_PAGEY2 + VYSIZE - i;
2600 int dst2_x = VX, dst2_y = VY;
2601 int width = VXSIZE, height = i;
2603 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2604 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2607 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2608 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2611 else if (x <= VXSIZE) /* ANIM_DEFAULT */
2613 int j = (door_2.anim_mode == ANIM_DEFAULT ? (VXSIZE - i) / 3 : 0);
2615 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2616 BlitBitmapMasked(bitmap, drawto,
2617 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
2618 VX + VXSIZE - i, VY + j);
2619 SetClipOrigin(bitmap, gc,
2620 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2621 BlitBitmapMasked(bitmap, drawto,
2622 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
2625 BlitBitmapMasked(bitmap, drawto,
2626 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2627 i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
2628 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2629 BlitBitmapMasked(bitmap, drawto,
2630 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2632 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2635 redraw_mask |= REDRAW_DOOR_2;
2636 door_2_done = (a == VXSIZE);
2641 if (game_status == GAME_MODE_MAIN)
2644 if (!(door_state & DOOR_NO_DELAY))
2645 WaitUntilDelayReached(&door_delay, door_delay_value);
2649 if (door_state & DOOR_ACTION_1)
2650 door1 = door_state & DOOR_ACTION_1;
2651 if (door_state & DOOR_ACTION_2)
2652 door2 = door_state & DOOR_ACTION_2;
2654 return (door1 | door2);
2657 void DrawSpecialEditorDoor()
2659 /* draw bigger toolbox window */
2660 BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
2661 DOOR_GFX_PAGEX7, 0, EXSIZE + 8, 8,
2663 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2664 EX - 4, VY - 4, EXSIZE + 8, EYSIZE - VYSIZE + 4,
2667 redraw_mask |= REDRAW_ALL;
2670 void UndrawSpecialEditorDoor()
2672 /* draw normal tape recorder window */
2673 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2674 EX - 4, EY - 12, EXSIZE + 8, EYSIZE - VYSIZE + 12,
2677 redraw_mask |= REDRAW_ALL;
2681 /* ---------- new tool button stuff ---------------------------------------- */
2683 /* graphic position values for tool buttons */
2684 #define TOOL_BUTTON_YES_XPOS 2
2685 #define TOOL_BUTTON_YES_YPOS 250
2686 #define TOOL_BUTTON_YES_GFX_YPOS 0
2687 #define TOOL_BUTTON_YES_XSIZE 46
2688 #define TOOL_BUTTON_YES_YSIZE 28
2689 #define TOOL_BUTTON_NO_XPOS 52
2690 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2691 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2692 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2693 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2694 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2695 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2696 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2697 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2698 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2699 #define TOOL_BUTTON_PLAYER_XSIZE 30
2700 #define TOOL_BUTTON_PLAYER_YSIZE 30
2701 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2702 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2703 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2704 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2705 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2706 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2707 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2708 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2709 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2710 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2711 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2712 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2713 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2714 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2715 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2716 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2717 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2718 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2719 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2720 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2729 } toolbutton_info[NUM_TOOL_BUTTONS] =
2732 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2733 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2734 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2739 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2740 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2741 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2746 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2747 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2748 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2749 TOOL_CTRL_ID_CONFIRM,
2753 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2754 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2755 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2756 TOOL_CTRL_ID_PLAYER_1,
2760 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2761 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2762 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2763 TOOL_CTRL_ID_PLAYER_2,
2767 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2768 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2769 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2770 TOOL_CTRL_ID_PLAYER_3,
2774 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2775 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2776 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2777 TOOL_CTRL_ID_PLAYER_4,
2782 void CreateToolButtons()
2786 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2788 Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2789 Bitmap *deco_bitmap = None;
2790 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2791 struct GadgetInfo *gi;
2792 unsigned long event_mask;
2793 int gd_xoffset, gd_yoffset;
2794 int gd_x1, gd_x2, gd_y;
2797 event_mask = GD_EVENT_RELEASED;
2799 gd_xoffset = toolbutton_info[i].xpos;
2800 gd_yoffset = toolbutton_info[i].ypos;
2801 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2802 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2803 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2805 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2807 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
2809 getMiniGraphicSource(PLAYER_NR_GFX(IMG_PLAYER_1, player_nr),
2810 &deco_bitmap, &deco_x, &deco_y);
2811 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2812 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2815 gi = CreateGadget(GDI_CUSTOM_ID, id,
2816 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2817 GDI_X, DX + toolbutton_info[i].x,
2818 GDI_Y, DY + toolbutton_info[i].y,
2819 GDI_WIDTH, toolbutton_info[i].width,
2820 GDI_HEIGHT, toolbutton_info[i].height,
2821 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2822 GDI_STATE, GD_BUTTON_UNPRESSED,
2823 GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
2824 GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
2825 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
2826 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2827 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2828 GDI_DECORATION_SHIFTING, 1, 1,
2829 GDI_EVENT_MASK, event_mask,
2830 GDI_CALLBACK_ACTION, HandleToolButtons,
2834 Error(ERR_EXIT, "cannot create gadget");
2836 tool_gadget[id] = gi;
2840 void FreeToolButtons()
2844 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2845 FreeGadget(tool_gadget[i]);
2848 static void UnmapToolButtons()
2852 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2853 UnmapGadget(tool_gadget[i]);
2856 static void HandleToolButtons(struct GadgetInfo *gi)
2858 request_gadget_id = gi->custom_id;
2861 static struct Mapping_EM_to_RND_object
2864 boolean is_rnd_to_em_mapping; /* unique mapping EM <-> RND */
2865 boolean is_backside; /* backside of moving element */
2871 em_object_mapping_list[] =
2874 Xblank, TRUE, FALSE,
2878 Yacid_splash_eB, FALSE, FALSE,
2879 EL_ACID_SPLASH_RIGHT, -1, -1
2882 Yacid_splash_wB, FALSE, FALSE,
2883 EL_ACID_SPLASH_LEFT, -1, -1
2886 #ifdef EM_ENGINE_BAD_ROLL
2888 Xstone_force_e, FALSE, FALSE,
2889 EL_ROCK, -1, MV_BIT_RIGHT
2892 Xstone_force_w, FALSE, FALSE,
2893 EL_ROCK, -1, MV_BIT_LEFT
2896 Xnut_force_e, FALSE, FALSE,
2897 EL_NUT, -1, MV_BIT_RIGHT
2900 Xnut_force_w, FALSE, FALSE,
2901 EL_NUT, -1, MV_BIT_LEFT
2904 Xspring_force_e, FALSE, FALSE,
2905 EL_SPRING, -1, MV_BIT_RIGHT
2908 Xspring_force_w, FALSE, FALSE,
2909 EL_SPRING, -1, MV_BIT_LEFT
2912 Xemerald_force_e, FALSE, FALSE,
2913 EL_EMERALD, -1, MV_BIT_RIGHT
2916 Xemerald_force_w, FALSE, FALSE,
2917 EL_EMERALD, -1, MV_BIT_LEFT
2920 Xdiamond_force_e, FALSE, FALSE,
2921 EL_DIAMOND, -1, MV_BIT_RIGHT
2924 Xdiamond_force_w, FALSE, FALSE,
2925 EL_DIAMOND, -1, MV_BIT_LEFT
2928 Xbomb_force_e, FALSE, FALSE,
2929 EL_BOMB, -1, MV_BIT_RIGHT
2932 Xbomb_force_w, FALSE, FALSE,
2933 EL_BOMB, -1, MV_BIT_LEFT
2935 #endif /* EM_ENGINE_BAD_ROLL */
2938 Xstone, TRUE, FALSE,
2942 Xstone_pause, FALSE, FALSE,
2946 Xstone_fall, FALSE, FALSE,
2950 Ystone_s, FALSE, FALSE,
2951 EL_ROCK, ACTION_FALLING, -1
2954 Ystone_sB, FALSE, TRUE,
2955 EL_ROCK, ACTION_FALLING, -1
2958 Ystone_e, FALSE, FALSE,
2959 EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT
2962 Ystone_eB, FALSE, TRUE,
2963 EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT
2966 Ystone_w, FALSE, FALSE,
2967 EL_ROCK, ACTION_MOVING, MV_BIT_LEFT
2970 Ystone_wB, FALSE, TRUE,
2971 EL_ROCK, ACTION_MOVING, MV_BIT_LEFT
2978 Xnut_pause, FALSE, FALSE,
2982 Xnut_fall, FALSE, FALSE,
2986 Ynut_s, FALSE, FALSE,
2987 EL_NUT, ACTION_FALLING, -1
2990 Ynut_sB, FALSE, TRUE,
2991 EL_NUT, ACTION_FALLING, -1
2994 Ynut_e, FALSE, FALSE,
2995 EL_NUT, ACTION_MOVING, MV_BIT_RIGHT
2998 Ynut_eB, FALSE, TRUE,
2999 EL_NUT, ACTION_MOVING, MV_BIT_RIGHT
3002 Ynut_w, FALSE, FALSE,
3003 EL_NUT, ACTION_MOVING, MV_BIT_LEFT
3006 Ynut_wB, FALSE, TRUE,
3007 EL_NUT, ACTION_MOVING, MV_BIT_LEFT
3010 Xbug_n, TRUE, FALSE,
3014 Xbug_e, TRUE, FALSE,
3015 EL_BUG_RIGHT, -1, -1
3018 Xbug_s, TRUE, FALSE,
3022 Xbug_w, TRUE, FALSE,
3026 Xbug_gon, FALSE, FALSE,
3030 Xbug_goe, FALSE, FALSE,
3031 EL_BUG_RIGHT, -1, -1
3034 Xbug_gos, FALSE, FALSE,
3038 Xbug_gow, FALSE, FALSE,
3042 Ybug_n, FALSE, FALSE,
3043 EL_BUG, ACTION_MOVING, MV_BIT_UP
3046 Ybug_nB, FALSE, TRUE,
3047 EL_BUG, ACTION_MOVING, MV_BIT_UP
3050 Ybug_e, FALSE, FALSE,
3051 EL_BUG, ACTION_MOVING, MV_BIT_RIGHT
3054 Ybug_eB, FALSE, TRUE,
3055 EL_BUG, ACTION_MOVING, MV_BIT_RIGHT
3058 Ybug_s, FALSE, FALSE,
3059 EL_BUG, ACTION_MOVING, MV_BIT_DOWN
3062 Ybug_sB, FALSE, TRUE,
3063 EL_BUG, ACTION_MOVING, MV_BIT_DOWN
3066 Ybug_w, FALSE, FALSE,
3067 EL_BUG, ACTION_MOVING, MV_BIT_LEFT
3070 Ybug_wB, FALSE, TRUE,
3071 EL_BUG, ACTION_MOVING, MV_BIT_LEFT
3074 Ybug_w_n, FALSE, FALSE,
3075 EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_UP
3078 Ybug_n_e, FALSE, FALSE,
3079 EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3082 Ybug_e_s, FALSE, FALSE,
3083 EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
3086 Ybug_s_w, FALSE, FALSE,
3087 EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3090 Ybug_e_n, FALSE, FALSE,
3091 EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
3094 Ybug_s_e, FALSE, FALSE,
3095 EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3098 Ybug_w_s, FALSE, FALSE,
3099 EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
3102 Ybug_n_w, FALSE, FALSE,
3103 EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3106 Ybug_stone, FALSE, FALSE,
3107 EL_BUG, ACTION_SMASHED_BY_ROCK, -1
3110 Ybug_spring, FALSE, FALSE,
3111 EL_BUG, ACTION_SMASHED_BY_SPRING, -1
3114 Xtank_n, TRUE, FALSE,
3115 EL_SPACESHIP_UP, -1, -1
3118 Xtank_e, TRUE, FALSE,
3119 EL_SPACESHIP_RIGHT, -1, -1
3122 Xtank_s, TRUE, FALSE,
3123 EL_SPACESHIP_DOWN, -1, -1
3126 Xtank_w, TRUE, FALSE,
3127 EL_SPACESHIP_LEFT, -1, -1
3130 Xtank_gon, FALSE, FALSE,
3131 EL_SPACESHIP_UP, -1, -1
3134 Xtank_goe, FALSE, FALSE,
3135 EL_SPACESHIP_RIGHT, -1, -1
3138 Xtank_gos, FALSE, FALSE,
3139 EL_SPACESHIP_DOWN, -1, -1
3142 Xtank_gow, FALSE, FALSE,
3143 EL_SPACESHIP_LEFT, -1, -1
3146 Ytank_n, FALSE, FALSE,
3147 EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP
3150 Ytank_nB, FALSE, TRUE,
3151 EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP
3154 Ytank_e, FALSE, FALSE,
3155 EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT
3158 Ytank_eB, FALSE, TRUE,
3159 EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT
3162 Ytank_s, FALSE, FALSE,
3163 EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN
3166 Ytank_sB, FALSE, TRUE,
3167 EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN
3170 Ytank_w, FALSE, FALSE,
3171 EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT
3174 Ytank_wB, FALSE, TRUE,
3175 EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT
3178 Ytank_w_n, FALSE, FALSE,
3179 EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_UP
3182 Ytank_n_e, FALSE, FALSE,
3183 EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3186 Ytank_e_s, FALSE, FALSE,
3187 EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
3190 Ytank_s_w, FALSE, FALSE,
3191 EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3194 Ytank_e_n, FALSE, FALSE,
3195 EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
3198 Ytank_s_e, FALSE, FALSE,
3199 EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3202 Ytank_w_s, FALSE, FALSE,
3203 EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
3206 Ytank_n_w, FALSE, FALSE,
3207 EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3210 Ytank_stone, FALSE, FALSE,
3211 EL_SPACESHIP, ACTION_SMASHED_BY_ROCK, -1
3214 Ytank_spring, FALSE, FALSE,
3215 EL_SPACESHIP, ACTION_SMASHED_BY_SPRING, -1
3218 Xandroid, TRUE, FALSE,
3219 EL_EMC_ANDROID, ACTION_ACTIVE, -1
3222 Xandroid_1_n, FALSE, FALSE,
3223 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_UP
3226 Xandroid_2_n, FALSE, FALSE,
3227 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_UP
3230 Xandroid_1_e, FALSE, FALSE,
3231 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_RIGHT
3234 Xandroid_2_e, FALSE, FALSE,
3235 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_RIGHT
3238 Xandroid_1_w, FALSE, FALSE,
3239 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_LEFT
3242 Xandroid_2_w, FALSE, FALSE,
3243 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_LEFT
3246 Xandroid_1_s, FALSE, FALSE,
3247 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_DOWN
3250 Xandroid_2_s, FALSE, FALSE,
3251 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_DOWN
3254 Yandroid_n, FALSE, FALSE,
3255 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_UP
3258 Yandroid_nB, FALSE, TRUE,
3259 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_UP
3262 Yandroid_ne, FALSE, FALSE,
3263 EL_EMC_ANDROID, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3266 Yandroid_neB, FALSE, TRUE,
3267 EL_EMC_ANDROID, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3270 Yandroid_e, FALSE, FALSE,
3271 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_RIGHT
3274 Yandroid_eB, FALSE, TRUE,
3275 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_RIGHT
3278 Yandroid_se, FALSE, FALSE,
3279 EL_EMC_ANDROID, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3282 Yandroid_seB, FALSE, TRUE,
3283 EL_EMC_ANDROID, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3286 Yandroid_s, FALSE, FALSE,
3287 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_DOWN
3290 Yandroid_sB, FALSE, TRUE,
3291 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_DOWN
3294 Yandroid_sw, FALSE, FALSE,
3295 EL_EMC_ANDROID, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3298 Yandroid_swB, FALSE, TRUE,
3299 EL_EMC_ANDROID, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3302 Yandroid_w, FALSE, FALSE,
3303 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_LEFT
3306 Yandroid_wB, FALSE, TRUE,
3307 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_LEFT
3310 Yandroid_nw, FALSE, FALSE,
3311 EL_EMC_ANDROID, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3314 Yandroid_nwB, FALSE, TRUE,
3315 EL_EMC_ANDROID, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3318 Xspring, TRUE, FALSE,
3322 Xspring_pause, FALSE, FALSE,
3326 Xspring_e, FALSE, FALSE,
3330 Xspring_w, FALSE, FALSE,
3334 Xspring_fall, FALSE, FALSE,
3338 Yspring_s, FALSE, FALSE,
3339 EL_SPRING, ACTION_FALLING, -1
3342 Yspring_sB, FALSE, TRUE,
3343 EL_SPRING, ACTION_FALLING, -1
3346 Yspring_e, FALSE, FALSE,
3347 EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT
3350 Yspring_eB, FALSE, TRUE,
3351 EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT
3354 Yspring_w, FALSE, FALSE,
3355 EL_SPRING, ACTION_MOVING, MV_BIT_LEFT
3358 Yspring_wB, FALSE, TRUE,
3359 EL_SPRING, ACTION_MOVING, MV_BIT_LEFT
3362 Yspring_kill_e, FALSE, FALSE,
3363 EL_ROBOT, ACTION_SLURPED_BY_SPRING, MV_BIT_RIGHT
3366 Yspring_kill_eB, FALSE, TRUE,
3367 EL_ROBOT, ACTION_SLURPED_BY_SPRING, MV_BIT_RIGHT
3370 Yspring_kill_w, FALSE, FALSE,
3371 EL_ROBOT, ACTION_SLURPED_BY_SPRING, MV_BIT_LEFT
3374 Yspring_kill_wB, FALSE, TRUE,
3375 EL_ROBOT, ACTION_SLURPED_BY_SPRING, MV_BIT_LEFT
3378 Xeater_n, TRUE, FALSE,
3382 Xeater_e, FALSE, FALSE,
3386 Xeater_w, FALSE, FALSE,
3390 Xeater_s, FALSE, FALSE,
3394 Yeater_n, FALSE, FALSE,
3395 EL_YAMYAM, ACTION_MOVING, MV_BIT_UP
3398 Yeater_nB, FALSE, TRUE,
3399 EL_YAMYAM, ACTION_MOVING, MV_BIT_UP
3402 Yeater_e, FALSE, FALSE,
3403 EL_YAMYAM, ACTION_MOVING, MV_BIT_RIGHT
3406 Yeater_eB, FALSE, TRUE,
3407 EL_YAMYAM, ACTION_MOVING, MV_BIT_RIGHT
3410 Yeater_s, FALSE, FALSE,
3411 EL_YAMYAM, ACTION_MOVING, MV_BIT_DOWN
3414 Yeater_sB, FALSE, TRUE,
3415 EL_YAMYAM, ACTION_MOVING, MV_BIT_DOWN
3418 Yeater_w, FALSE, FALSE,
3419 EL_YAMYAM, ACTION_MOVING, MV_BIT_LEFT
3422 Yeater_wB, FALSE, TRUE,
3423 EL_YAMYAM, ACTION_MOVING, MV_BIT_LEFT
3426 Yeater_stone, FALSE, FALSE,
3427 EL_YAMYAM, ACTION_SMASHED_BY_ROCK, -1
3430 Yeater_spring, FALSE, FALSE,
3431 EL_YAMYAM, ACTION_SMASHED_BY_SPRING, -1
3434 Xalien, TRUE, FALSE,
3438 Xalien_pause, FALSE, FALSE,
3442 Yalien_n, FALSE, FALSE,
3443 EL_ROBOT, ACTION_MOVING, MV_BIT_UP
3446 Yalien_nB, FALSE, TRUE,
3447 EL_ROBOT, ACTION_MOVING, MV_BIT_UP
3450 Yalien_e, FALSE, FALSE,
3451 EL_ROBOT, ACTION_MOVING, MV_BIT_RIGHT
3454 Yalien_eB, FALSE, TRUE,
3455 EL_ROBOT, ACTION_MOVING, MV_BIT_RIGHT
3458 Yalien_s, FALSE, FALSE,
3459 EL_ROBOT, ACTION_MOVING, MV_BIT_DOWN
3462 Yalien_sB, FALSE, TRUE,
3463 EL_ROBOT, ACTION_MOVING, MV_BIT_DOWN
3466 Yalien_w, FALSE, FALSE,
3467 EL_ROBOT, ACTION_MOVING, MV_BIT_LEFT
3470 Yalien_wB, FALSE, TRUE,
3471 EL_ROBOT, ACTION_MOVING, MV_BIT_LEFT
3474 Yalien_stone, FALSE, FALSE,
3475 EL_ROBOT, ACTION_SMASHED_BY_ROCK, -1
3478 Yalien_spring, FALSE, FALSE,
3479 EL_ROBOT, ACTION_SMASHED_BY_SPRING, -1
3482 Xemerald, TRUE, FALSE,
3486 Xemerald_pause, FALSE, FALSE,
3490 Xemerald_fall, FALSE, FALSE,
3494 Xemerald_shine, FALSE, FALSE,
3495 EL_EMERALD, ACTION_TWINKLING, -1
3498 Yemerald_s, FALSE, FALSE,
3499 EL_EMERALD, ACTION_FALLING, -1
3502 Yemerald_sB, FALSE, TRUE,
3503 EL_EMERALD, ACTION_FALLING, -1
3506 Yemerald_e, FALSE, FALSE,
3507 EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT
3510 Yemerald_eB, FALSE, TRUE,
3511 EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT
3514 Yemerald_w, FALSE, FALSE,
3515 EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT
3518 Yemerald_wB, FALSE, TRUE,
3519 EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT
3522 Yemerald_eat, FALSE, FALSE,
3523 EL_EMERALD, ACTION_COLLECTING, -1
3526 Yemerald_stone, FALSE, FALSE,
3527 EL_NUT, ACTION_BREAKING, -1
3530 Xdiamond, TRUE, FALSE,
3534 Xdiamond_pause, FALSE, FALSE,
3538 Xdiamond_fall, FALSE, FALSE,
3542 Xdiamond_shine, FALSE, FALSE,
3543 EL_DIAMOND, ACTION_TWINKLING, -1
3546 Ydiamond_s, FALSE, FALSE,
3547 EL_DIAMOND, ACTION_FALLING, -1
3550 Ydiamond_sB, FALSE, TRUE,
3551 EL_DIAMOND, ACTION_FALLING, -1
3554 Ydiamond_e, FALSE, FALSE,
3555 EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT
3558 Ydiamond_eB, FALSE, TRUE,
3559 EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT
3562 Ydiamond_w, FALSE, FALSE,
3563 EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT
3566 Ydiamond_wB, FALSE, TRUE,
3567 EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT
3570 Ydiamond_eat, FALSE, FALSE,
3571 EL_DIAMOND, ACTION_COLLECTING, -1
3574 Ydiamond_stone, FALSE, FALSE,
3575 EL_DIAMOND, ACTION_SMASHED_BY_ROCK, -1
3578 Xdrip_fall, TRUE, FALSE,
3579 EL_AMOEBA_DROP, -1, -1
3582 Xdrip_stretch, FALSE, FALSE,
3583 EL_AMOEBA_DROP, ACTION_FALLING, -1
3586 Xdrip_stretchB, FALSE, TRUE,
3587 EL_AMOEBA_DROP, ACTION_FALLING, -1
3590 Xdrip_eat, FALSE, FALSE,
3591 EL_AMOEBA_DROP, ACTION_GROWING, -1
3594 Ydrip_s1, FALSE, FALSE,
3595 EL_AMOEBA_DROP, ACTION_FALLING, -1
3598 Ydrip_s1B, FALSE, TRUE,
3599 EL_AMOEBA_DROP, ACTION_FALLING, -1
3602 Ydrip_s2, FALSE, FALSE,
3603 EL_AMOEBA_DROP, ACTION_FALLING, -1
3606 Ydrip_s2B, FALSE, TRUE,
3607 EL_AMOEBA_DROP, ACTION_FALLING, -1
3614 Xbomb_pause, FALSE, FALSE,
3618 Xbomb_fall, FALSE, FALSE,
3622 Ybomb_s, FALSE, FALSE,
3623 EL_BOMB, ACTION_FALLING, -1
3626 Ybomb_sB, FALSE, TRUE,
3627 EL_BOMB, ACTION_FALLING, -1
3630 Ybomb_e, FALSE, FALSE,
3631 EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT
3634 Ybomb_eB, FALSE, TRUE,
3635 EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT
3638 Ybomb_w, FALSE, FALSE,
3639 EL_BOMB, ACTION_MOVING, MV_BIT_LEFT
3642 Ybomb_wB, FALSE, TRUE,
3643 EL_BOMB, ACTION_MOVING, MV_BIT_LEFT
3646 Ybomb_eat, FALSE, FALSE,
3647 EL_BOMB, ACTION_ACTIVATING, -1
3650 Xballoon, TRUE, FALSE,
3654 Yballoon_n, FALSE, FALSE,
3655 EL_BALLOON, ACTION_MOVING, MV_BIT_UP
3658 Yballoon_nB, FALSE, TRUE,
3659 EL_BALLOON, ACTION_MOVING, MV_BIT_UP
3662 Yballoon_e, FALSE, FALSE,
3663 EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT
3666 Yballoon_eB, FALSE, TRUE,
3667 EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT
3670 Yballoon_s, FALSE, FALSE,
3671 EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN
3674 Yballoon_sB, FALSE, TRUE,
3675 EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN
3678 Yballoon_w, FALSE, FALSE,
3679 EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT
3682 Yballoon_wB, FALSE, TRUE,
3683 EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT
3686 Xgrass, TRUE, FALSE,
3687 EL_EMC_GRASS, -1, -1
3690 Ygrass_nB, FALSE, FALSE,
3691 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_UP
3694 Ygrass_eB, FALSE, FALSE,
3695 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_RIGHT
3698 Ygrass_sB, FALSE, FALSE,
3699 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_DOWN
3702 Ygrass_wB, FALSE, FALSE,
3703 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_LEFT
3710 Ydirt_nB, FALSE, FALSE,
3711 EL_SAND, ACTION_DIGGING, MV_BIT_UP
3714 Ydirt_eB, FALSE, FALSE,
3715 EL_SAND, ACTION_DIGGING, MV_BIT_RIGHT
3718 Ydirt_sB, FALSE, FALSE,
3719 EL_SAND, ACTION_DIGGING, MV_BIT_DOWN
3722 Ydirt_wB, FALSE, FALSE,
3723 EL_SAND, ACTION_DIGGING, MV_BIT_LEFT
3726 Xacid_ne, TRUE, FALSE,
3727 EL_ACID_POOL_TOPRIGHT, -1, -1
3730 Xacid_se, TRUE, FALSE,
3731 EL_ACID_POOL_BOTTOMRIGHT, -1, -1
3734 Xacid_s, TRUE, FALSE,
3735 EL_ACID_POOL_BOTTOM, -1, -1
3738 Xacid_sw, TRUE, FALSE,
3739 EL_ACID_POOL_BOTTOMLEFT, -1, -1
3742 Xacid_nw, TRUE, FALSE,
3743 EL_ACID_POOL_TOPLEFT, -1, -1
3746 Xacid_1, TRUE, FALSE,
3750 Xacid_2, FALSE, FALSE,
3754 Xacid_3, FALSE, FALSE,
3758 Xacid_4, FALSE, FALSE,
3762 Xacid_5, FALSE, FALSE,
3766 Xacid_6, FALSE, FALSE,
3770 Xacid_7, FALSE, FALSE,
3774 Xacid_8, FALSE, FALSE,
3778 Xball_1, TRUE, FALSE,
3779 EL_EMC_MAGIC_BALL, -1, -1
3782 Xball_1B, FALSE, FALSE,
3783 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
3786 Xball_2, FALSE, FALSE,
3787 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
3790 Xball_2B, FALSE, FALSE,
3791 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
3794 Yball_eat, FALSE, FALSE,
3795 EL_EMC_MAGIC_BALL, ACTION_DROPPING, -1
3798 Ykey_1_eat, FALSE, FALSE,
3799 EL_EM_KEY_1, ACTION_COLLECTING, -1
3802 Ykey_2_eat, FALSE, FALSE,
3803 EL_EM_KEY_2, ACTION_COLLECTING, -1
3806 Ykey_3_eat, FALSE, FALSE,
3807 EL_EM_KEY_3, ACTION_COLLECTING, -1
3810 Ykey_4_eat, FALSE, FALSE,
3811 EL_EM_KEY_4, ACTION_COLLECTING, -1
3814 Ykey_5_eat, FALSE, FALSE,
3815 EL_EMC_KEY_5, ACTION_COLLECTING, -1
3818 Ykey_6_eat, FALSE, FALSE,
3819 EL_EMC_KEY_6, ACTION_COLLECTING, -1
3822 Ykey_7_eat, FALSE, FALSE,
3823 EL_EMC_KEY_7, ACTION_COLLECTING, -1
3826 Ykey_8_eat, FALSE, FALSE,
3827 EL_EMC_KEY_8, ACTION_COLLECTING, -1
3830 Ylenses_eat, FALSE, FALSE,
3831 EL_EMC_LENSES, ACTION_COLLECTING, -1
3834 Ymagnify_eat, FALSE, FALSE,
3835 EL_EMC_MAGNIFIER, ACTION_COLLECTING, -1
3838 Ygrass_eat, FALSE, FALSE,
3839 EL_EMC_GRASS, ACTION_SNAPPING, -1
3842 Ydirt_eat, FALSE, FALSE,
3843 EL_SAND, ACTION_SNAPPING, -1
3846 Xgrow_ns, TRUE, FALSE,
3847 EL_EXPANDABLE_WALL_VERTICAL, -1, -1
3850 Ygrow_ns_eat, FALSE, FALSE,
3851 EL_EXPANDABLE_WALL_VERTICAL, ACTION_GROWING, -1
3854 Xgrow_ew, TRUE, FALSE,
3855 EL_EXPANDABLE_WALL_HORIZONTAL, -1, -1
3858 Ygrow_ew_eat, FALSE, FALSE,
3859 EL_EXPANDABLE_WALL_HORIZONTAL, ACTION_GROWING, -1
3862 Xwonderwall, TRUE, FALSE,
3863 EL_MAGIC_WALL, -1, -1
3866 XwonderwallB, FALSE, FALSE,
3867 EL_MAGIC_WALL, ACTION_ACTIVE, -1
3870 Xamoeba_1, TRUE, FALSE,
3871 EL_AMOEBA_DRY, ACTION_OTHER, -1
3874 Xamoeba_2, FALSE, FALSE,
3875 EL_AMOEBA_DRY, ACTION_OTHER, -1
3878 Xamoeba_3, FALSE, FALSE,
3879 EL_AMOEBA_DRY, ACTION_OTHER, -1
3882 Xamoeba_4, FALSE, FALSE,
3883 EL_AMOEBA_DRY, ACTION_OTHER, -1
3886 Xamoeba_5, TRUE, FALSE,
3887 EL_AMOEBA_WET, ACTION_OTHER, -1
3890 Xamoeba_6, FALSE, FALSE,
3891 EL_AMOEBA_WET, ACTION_OTHER, -1
3894 Xamoeba_7, FALSE, FALSE,
3895 EL_AMOEBA_WET, ACTION_OTHER, -1
3898 Xamoeba_8, FALSE, FALSE,
3899 EL_AMOEBA_WET, ACTION_OTHER, -1
3902 Xdoor_1, TRUE, FALSE,
3903 EL_EM_GATE_1, -1, -1
3906 Xdoor_2, TRUE, FALSE,
3907 EL_EM_GATE_2, -1, -1
3910 Xdoor_3, TRUE, FALSE,
3911 EL_EM_GATE_3, -1, -1
3914 Xdoor_4, TRUE, FALSE,
3915 EL_EM_GATE_4, -1, -1
3918 Xdoor_5, TRUE, FALSE,
3919 EL_EMC_GATE_5, -1, -1
3922 Xdoor_6, TRUE, FALSE,
3923 EL_EMC_GATE_6, -1, -1
3926 Xdoor_7, TRUE, FALSE,
3927 EL_EMC_GATE_7, -1, -1
3930 Xdoor_8, TRUE, FALSE,
3931 EL_EMC_GATE_8, -1, -1
3934 Xkey_1, TRUE, FALSE,
3938 Xkey_2, TRUE, FALSE,
3942 Xkey_3, TRUE, FALSE,
3946 Xkey_4, TRUE, FALSE,
3950 Xkey_5, TRUE, FALSE,
3951 EL_EMC_KEY_5, -1, -1
3954 Xkey_6, TRUE, FALSE,
3955 EL_EMC_KEY_6, -1, -1
3958 Xkey_7, TRUE, FALSE,
3959 EL_EMC_KEY_7, -1, -1
3962 Xkey_8, TRUE, FALSE,
3963 EL_EMC_KEY_8, -1, -1
3966 Xwind_n, TRUE, FALSE,
3967 EL_BALLOON_SWITCH_UP, -1, -1
3970 Xwind_e, TRUE, FALSE,
3971 EL_BALLOON_SWITCH_RIGHT, -1, -1
3974 Xwind_s, TRUE, FALSE,
3975 EL_BALLOON_SWITCH_DOWN, -1, -1
3978 Xwind_w, TRUE, FALSE,
3979 EL_BALLOON_SWITCH_LEFT, -1, -1
3982 Xwind_nesw, TRUE, FALSE,
3983 EL_BALLOON_SWITCH_ANY, -1, -1
3986 Xwind_stop, TRUE, FALSE,
3987 EL_BALLOON_SWITCH_NONE, -1, -1
3991 EL_EXIT_CLOSED, -1, -1
3994 Xexit_1, TRUE, FALSE,
3995 EL_EXIT_OPEN, -1, -1
3998 Xexit_2, FALSE, FALSE,
3999 EL_EXIT_OPEN, -1, -1
4002 Xexit_3, FALSE, FALSE,
4003 EL_EXIT_OPEN, -1, -1
4006 Xdynamite, TRUE, FALSE,
4010 Ydynamite_eat, FALSE, FALSE,
4011 EL_DYNAMITE, ACTION_COLLECTING, -1
4014 Xdynamite_1, TRUE, FALSE,
4015 EL_DYNAMITE_ACTIVE, -1, -1
4018 Xdynamite_2, FALSE, FALSE,
4019 EL_DYNAMITE_ACTIVE, -1, -1
4022 Xdynamite_3, FALSE, FALSE,
4023 EL_DYNAMITE_ACTIVE, -1, -1
4026 Xdynamite_4, FALSE, FALSE,
4027 EL_DYNAMITE_ACTIVE, -1, -1
4030 Xbumper, TRUE, FALSE,
4031 EL_EMC_SPRING_BUMPER, -1, -1
4034 XbumperB, FALSE, FALSE,
4035 EL_EMC_SPRING_BUMPER, ACTION_ACTIVE, -1
4038 Xwheel, TRUE, FALSE,
4039 EL_ROBOT_WHEEL, -1, -1
4042 XwheelB, FALSE, FALSE,
4043 EL_ROBOT_WHEEL, ACTION_ACTIVE, -1
4046 Xswitch, TRUE, FALSE,
4047 EL_EMC_MAGIC_BALL_SWITCH, -1, -1
4050 XswitchB, FALSE, FALSE,
4051 EL_EMC_MAGIC_BALL_SWITCH, ACTION_ACTIVE, -1
4055 EL_QUICKSAND_EMPTY, -1, -1
4058 Xsand_stone, TRUE, FALSE,
4059 EL_QUICKSAND_FULL, -1, -1
4062 Xsand_stonein_1, FALSE, FALSE,
4063 EL_ROCK, ACTION_FILLING, -1
4066 Xsand_stonein_2, FALSE, FALSE,
4067 EL_ROCK, ACTION_FILLING, -1
4070 Xsand_stonein_3, FALSE, FALSE,
4071 EL_ROCK, ACTION_FILLING, -1
4074 Xsand_stonein_4, FALSE, FALSE,
4075 EL_ROCK, ACTION_FILLING, -1
4078 Xsand_stonesand_1, FALSE, FALSE,
4079 EL_QUICKSAND_FULL, -1, -1
4082 Xsand_stonesand_2, FALSE, FALSE,
4083 EL_QUICKSAND_FULL, -1, -1
4086 Xsand_stonesand_3, FALSE, FALSE,
4087 EL_QUICKSAND_FULL, -1, -1
4090 Xsand_stonesand_4, FALSE, FALSE,
4091 EL_QUICKSAND_FULL, -1, -1
4094 Xsand_stoneout_1, FALSE, FALSE,
4095 EL_ROCK, ACTION_EMPTYING, -1
4098 Xsand_stoneout_2, FALSE, FALSE,
4099 EL_ROCK, ACTION_EMPTYING, -1
4102 Xsand_sandstone_1, FALSE, FALSE,
4103 EL_QUICKSAND_FULL, -1, -1
4106 Xsand_sandstone_2, FALSE, FALSE,
4107 EL_QUICKSAND_FULL, -1, -1
4110 Xsand_sandstone_3, FALSE, FALSE,
4111 EL_QUICKSAND_FULL, -1, -1
4114 Xsand_sandstone_4, FALSE, FALSE,
4115 EL_QUICKSAND_FULL, -1, -1
4118 Xplant, TRUE, FALSE,
4119 EL_EMC_PLANT, -1, -1
4122 Yplant, FALSE, FALSE,
4123 EL_EMC_PLANT, -1, -1
4126 Xlenses, TRUE, FALSE,
4127 EL_EMC_LENSES, -1, -1
4130 Xmagnify, TRUE, FALSE,
4131 EL_EMC_MAGNIFIER, -1, -1
4134 Xdripper, TRUE, FALSE,
4135 EL_EMC_DRIPPER, -1, -1
4138 XdripperB, FALSE, FALSE,
4139 EL_EMC_DRIPPER, ACTION_ACTIVE, -1
4142 Xfake_blank, TRUE, FALSE,
4143 EL_INVISIBLE_WALL, -1, -1
4146 Xfake_blankB, FALSE, FALSE,
4147 EL_INVISIBLE_WALL, ACTION_ACTIVE, -1
4150 Xfake_grass, TRUE, FALSE,
4151 EL_EMC_FAKE_GRASS, -1, -1
4154 Xfake_grassB, FALSE, FALSE,
4155 EL_EMC_FAKE_GRASS, ACTION_ACTIVE, -1
4158 Xfake_door_1, TRUE, FALSE,
4159 EL_EM_GATE_1_GRAY, -1, -1
4162 Xfake_door_2, TRUE, FALSE,
4163 EL_EM_GATE_2_GRAY, -1, -1
4166 Xfake_door_3, TRUE, FALSE,
4167 EL_EM_GATE_3_GRAY, -1, -1
4170 Xfake_door_4, TRUE, FALSE,
4171 EL_EM_GATE_4_GRAY, -1, -1
4174 Xfake_door_5, TRUE, FALSE,
4175 EL_EMC_GATE_5_GRAY, -1, -1
4178 Xfake_door_6, TRUE, FALSE,
4179 EL_EMC_GATE_6_GRAY, -1, -1
4182 Xfake_door_7, TRUE, FALSE,
4183 EL_EMC_GATE_7_GRAY, -1, -1
4186 Xfake_door_8, TRUE, FALSE,
4187 EL_EMC_GATE_8_GRAY, -1, -1
4190 Xfake_acid_1, TRUE, FALSE,
4191 EL_EMC_FAKE_ACID, -1, -1
4194 Xfake_acid_2, FALSE, FALSE,
4195 EL_EMC_FAKE_ACID, -1, -1
4198 Xfake_acid_3, FALSE, FALSE,
4199 EL_EMC_FAKE_ACID, -1, -1
4202 Xfake_acid_4, FALSE, FALSE,
4203 EL_EMC_FAKE_ACID, -1, -1
4206 Xfake_acid_5, FALSE, FALSE,
4207 EL_EMC_FAKE_ACID, -1, -1
4210 Xfake_acid_6, FALSE, FALSE,
4211 EL_EMC_FAKE_ACID, -1, -1
4214 Xfake_acid_7, FALSE, FALSE,
4215 EL_EMC_FAKE_ACID, -1, -1
4218 Xfake_acid_8, FALSE, FALSE,
4219 EL_EMC_FAKE_ACID, -1, -1
4222 Xsteel_1, TRUE, FALSE,
4223 EL_STEELWALL, -1, -1
4226 Xsteel_2, TRUE, FALSE,
4227 EL_EMC_STEELWALL_2, -1, -1
4230 Xsteel_3, TRUE, FALSE,
4231 EL_EMC_STEELWALL_3, -1, -1
4234 Xsteel_4, TRUE, FALSE,
4235 EL_EMC_STEELWALL_4, -1, -1
4238 Xwall_1, TRUE, FALSE,
4242 Xwall_2, TRUE, FALSE,
4243 EL_EMC_WALL_14, -1, -1
4246 Xwall_3, TRUE, FALSE,
4247 EL_EMC_WALL_15, -1, -1
4250 Xwall_4, TRUE, FALSE,
4251 EL_EMC_WALL_16, -1, -1
4254 Xround_wall_1, TRUE, FALSE,
4255 EL_WALL_SLIPPERY, -1, -1
4258 Xround_wall_2, TRUE, FALSE,
4259 EL_EMC_WALL_SLIPPERY_2, -1, -1
4262 Xround_wall_3, TRUE, FALSE,
4263 EL_EMC_WALL_SLIPPERY_3, -1, -1
4266 Xround_wall_4, TRUE, FALSE,
4267 EL_EMC_WALL_SLIPPERY_4, -1, -1
4270 Xdecor_1, TRUE, FALSE,
4271 EL_EMC_WALL_8, -1, -1
4274 Xdecor_2, TRUE, FALSE,
4275 EL_EMC_WALL_6, -1, -1
4278 Xdecor_3, TRUE, FALSE,
4279 EL_EMC_WALL_4, -1, -1
4282 Xdecor_4, TRUE, FALSE,
4283 EL_EMC_WALL_7, -1, -1
4286 Xdecor_5, TRUE, FALSE,
4287 EL_EMC_WALL_5, -1, -1
4290 Xdecor_6, TRUE, FALSE,
4291 EL_EMC_WALL_9, -1, -1
4294 Xdecor_7, TRUE, FALSE,
4295 EL_EMC_WALL_10, -1, -1
4298 Xdecor_8, TRUE, FALSE,
4299 EL_EMC_WALL_1, -1, -1
4302 Xdecor_9, TRUE, FALSE,
4303 EL_EMC_WALL_2, -1, -1
4306 Xdecor_10, TRUE, FALSE,
4307 EL_EMC_WALL_3, -1, -1
4310 Xdecor_11, TRUE, FALSE,
4311 EL_EMC_WALL_11, -1, -1
4314 Xdecor_12, TRUE, FALSE,
4315 EL_EMC_WALL_12, -1, -1
4318 Xalpha_0, TRUE, FALSE,
4319 EL_CHAR('0'), -1, -1
4322 Xalpha_1, TRUE, FALSE,
4323 EL_CHAR('1'), -1, -1
4326 Xalpha_2, TRUE, FALSE,
4327 EL_CHAR('2'), -1, -1
4330 Xalpha_3, TRUE, FALSE,
4331 EL_CHAR('3'), -1, -1
4334 Xalpha_4, TRUE, FALSE,
4335 EL_CHAR('4'), -1, -1
4338 Xalpha_5, TRUE, FALSE,
4339 EL_CHAR('5'), -1, -1
4342 Xalpha_6, TRUE, FALSE,
4343 EL_CHAR('6'), -1, -1
4346 Xalpha_7, TRUE, FALSE,
4347 EL_CHAR('7'), -1, -1
4350 Xalpha_8, TRUE, FALSE,
4351 EL_CHAR('8'), -1, -1
4354 Xalpha_9, TRUE, FALSE,
4355 EL_CHAR('9'), -1, -1
4358 Xalpha_excla, TRUE, FALSE,
4359 EL_CHAR('!'), -1, -1
4362 Xalpha_quote, TRUE, FALSE,
4363 EL_CHAR('"'), -1, -1
4366 Xalpha_comma, TRUE, FALSE,
4367 EL_CHAR(','), -1, -1
4370 Xalpha_minus, TRUE, FALSE,
4371 EL_CHAR('-'), -1, -1
4374 Xalpha_perio, TRUE, FALSE,
4375 EL_CHAR('.'), -1, -1
4378 Xalpha_colon, TRUE, FALSE,
4379 EL_CHAR(':'), -1, -1
4382 Xalpha_quest, TRUE, FALSE,
4383 EL_CHAR('?'), -1, -1
4386 Xalpha_a, TRUE, FALSE,
4387 EL_CHAR('A'), -1, -1
4390 Xalpha_b, TRUE, FALSE,
4391 EL_CHAR('B'), -1, -1
4394 Xalpha_c, TRUE, FALSE,
4395 EL_CHAR('C'), -1, -1
4398 Xalpha_d, TRUE, FALSE,
4399 EL_CHAR('D'), -1, -1
4402 Xalpha_e, TRUE, FALSE,
4403 EL_CHAR('E'), -1, -1
4406 Xalpha_f, TRUE, FALSE,
4407 EL_CHAR('F'), -1, -1
4410 Xalpha_g, TRUE, FALSE,
4411 EL_CHAR('G'), -1, -1
4414 Xalpha_h, TRUE, FALSE,
4415 EL_CHAR('H'), -1, -1
4418 Xalpha_i, TRUE, FALSE,
4419 EL_CHAR('I'), -1, -1
4422 Xalpha_j, TRUE, FALSE,
4423 EL_CHAR('J'), -1, -1
4426 Xalpha_k, TRUE, FALSE,
4427 EL_CHAR('K'), -1, -1
4430 Xalpha_l, TRUE, FALSE,
4431 EL_CHAR('L'), -1, -1
4434 Xalpha_m, TRUE, FALSE,
4435 EL_CHAR('M'), -1, -1
4438 Xalpha_n, TRUE, FALSE,
4439 EL_CHAR('N'), -1, -1
4442 Xalpha_o, TRUE, FALSE,
4443 EL_CHAR('O'), -1, -1
4446 Xalpha_p, TRUE, FALSE,
4447 EL_CHAR('P'), -1, -1
4450 Xalpha_q, TRUE, FALSE,
4451 EL_CHAR('Q'), -1, -1
4454 Xalpha_r, TRUE, FALSE,
4455 EL_CHAR('R'), -1, -1
4458 Xalpha_s, TRUE, FALSE,
4459 EL_CHAR('S'), -1, -1
4462 Xalpha_t, TRUE, FALSE,
4463 EL_CHAR('T'), -1, -1
4466 Xalpha_u, TRUE, FALSE,
4467 EL_CHAR('U'), -1, -1
4470 Xalpha_v, TRUE, FALSE,
4471 EL_CHAR('V'), -1, -1
4474 Xalpha_w, TRUE, FALSE,
4475 EL_CHAR('W'), -1, -1
4478 Xalpha_x, TRUE, FALSE,
4479 EL_CHAR('X'), -1, -1
4482 Xalpha_y, TRUE, FALSE,
4483 EL_CHAR('Y'), -1, -1
4486 Xalpha_z, TRUE, FALSE,
4487 EL_CHAR('Z'), -1, -1
4490 Xalpha_arrow_e, TRUE, FALSE,
4491 EL_CHAR('>'), -1, -1
4494 Xalpha_arrow_w, TRUE, FALSE,
4495 EL_CHAR('<'), -1, -1
4498 Xalpha_copyr, TRUE, FALSE,
4499 EL_CHAR('©'), -1, -1
4502 Xalpha_copyr, TRUE, FALSE,
4503 EL_CHAR('©'), -1, -1
4507 Xboom_bug, FALSE, FALSE,
4508 EL_BUG, ACTION_EXPLODING, -1
4511 Xboom_bomb, FALSE, FALSE,
4512 EL_BOMB, ACTION_EXPLODING, -1
4515 Xboom_android, FALSE, FALSE,
4516 EL_EMC_ANDROID, ACTION_OTHER, -1
4519 Xboom_1, FALSE, FALSE,
4520 EL_DEFAULT, ACTION_EXPLODING, -1
4523 Xboom_2, FALSE, FALSE,
4524 EL_DEFAULT, ACTION_EXPLODING, -1
4527 Znormal, FALSE, FALSE,
4531 Zdynamite, FALSE, FALSE,
4535 Zplayer, FALSE, FALSE,
4539 ZBORDER, FALSE, FALSE,
4549 static struct Mapping_EM_to_RND_player
4558 em_player_mapping_list[] =
4562 EL_PLAYER_1, ACTION_MOVING, MV_BIT_UP,
4566 EL_PLAYER_1, ACTION_MOVING, MV_BIT_RIGHT,
4570 EL_PLAYER_1, ACTION_MOVING, MV_BIT_DOWN,
4574 EL_PLAYER_1, ACTION_MOVING, MV_BIT_LEFT,
4578 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_UP,
4582 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_RIGHT,
4586 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_DOWN,
4590 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_LEFT,
4594 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_UP,
4598 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_RIGHT,
4602 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_DOWN,
4606 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_LEFT,
4610 EL_PLAYER_2, ACTION_MOVING, MV_BIT_UP,
4614 EL_PLAYER_2, ACTION_MOVING, MV_BIT_RIGHT,
4618 EL_PLAYER_2, ACTION_MOVING, MV_BIT_DOWN,
4622 EL_PLAYER_2, ACTION_MOVING, MV_BIT_LEFT,
4626 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_UP,
4630 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_RIGHT,
4634 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_DOWN,
4638 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_LEFT,
4642 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_UP,
4646 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_RIGHT,
4650 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_DOWN,
4654 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_LEFT,
4658 EL_PLAYER_1, ACTION_DEFAULT, -1,
4662 EL_PLAYER_2, ACTION_DEFAULT, -1,
4671 int map_element_RND_to_EM(int element_rnd)
4673 static unsigned short mapping_RND_to_EM[NUM_FILE_ELEMENTS];
4674 static boolean mapping_initialized = FALSE;
4676 if (!mapping_initialized)
4680 /* return "Xalpha_quest" for all undefined elements in mapping array */
4681 for (i = 0; i < NUM_FILE_ELEMENTS; i++)
4682 mapping_RND_to_EM[i] = Xalpha_quest;
4684 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
4685 if (em_object_mapping_list[i].is_rnd_to_em_mapping)
4686 mapping_RND_to_EM[em_object_mapping_list[i].element_rnd] =
4687 em_object_mapping_list[i].element_em;
4689 mapping_initialized = TRUE;
4692 if (element_rnd >= 0 && element_rnd < NUM_FILE_ELEMENTS)
4693 return mapping_RND_to_EM[element_rnd];
4695 Error(ERR_WARN, "invalid RND level element %d", element_rnd);
4700 int map_element_EM_to_RND(int element_em)
4702 static unsigned short mapping_EM_to_RND[TILE_MAX];
4703 static boolean mapping_initialized = FALSE;
4705 if (!mapping_initialized)
4709 /* return "EL_UNKNOWN" for all undefined elements in mapping array */
4710 for (i = 0; i < TILE_MAX; i++)
4711 mapping_EM_to_RND[i] = EL_UNKNOWN;
4713 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
4714 mapping_EM_to_RND[em_object_mapping_list[i].element_em] =
4715 em_object_mapping_list[i].element_rnd;
4717 mapping_initialized = TRUE;
4720 if (element_em >= 0 && element_em < TILE_MAX)
4721 return mapping_EM_to_RND[element_em];
4723 Error(ERR_WARN, "invalid EM level element %d", element_em);
4730 int map_element_RND_to_EM(int element_rnd)
4732 static unsigned short mapping_RND_to_EM[NUM_FILE_ELEMENTS];
4733 static boolean mapping_initialized = FALSE;
4740 mapping_RND_to_EM_list[] =
4742 { Xblank, EL_EMPTY },
4743 { Xstone, EL_ROCK },
4745 { Xbug_n, EL_BUG_UP },
4746 { Xbug_e, EL_BUG_RIGHT },
4747 { Xbug_s, EL_BUG_DOWN },
4748 { Xbug_w, EL_BUG_LEFT },
4749 { Xtank_n, EL_SPACESHIP_UP },
4750 { Xtank_e, EL_SPACESHIP_RIGHT },
4751 { Xtank_s, EL_SPACESHIP_DOWN },
4752 { Xtank_w, EL_SPACESHIP_LEFT },
4753 { Xandroid, EL_EMC_ANDROID },
4754 { Xandroid_1_n, EL_EMC_ANDROID_UP },
4755 { Xandroid_1_e, EL_EMC_ANDROID_RIGHT },
4756 { Xandroid_1_w, EL_EMC_ANDROID_LEFT },
4757 { Xandroid_1_s, EL_EMC_ANDROID_DOWN },
4758 { Xspring, EL_SPRING },
4759 { Xeater_n, EL_YAMYAM },
4760 { Xalien, EL_ROBOT },
4761 { Xemerald, EL_EMERALD },
4762 { Xdiamond, EL_DIAMOND },
4763 { Xdrip_fall, EL_AMOEBA_DROP },
4765 { Xballoon, EL_BALLOON },
4766 { Xgrass, EL_EMC_GRASS },
4768 { Xacid_ne, EL_ACID_POOL_TOPRIGHT },
4769 { Xacid_se, EL_ACID_POOL_BOTTOMRIGHT },
4770 { Xacid_s, EL_ACID_POOL_BOTTOM },
4771 { Xacid_sw, EL_ACID_POOL_BOTTOMLEFT },
4772 { Xacid_nw, EL_ACID_POOL_TOPLEFT },
4773 { Xacid_1, EL_ACID },
4774 { Xball_1, EL_EMC_MAGIC_BALL },
4775 { Xgrow_ns, EL_EMC_GROW },
4776 { Xwonderwall, EL_MAGIC_WALL },
4777 { Xamoeba_1, EL_AMOEBA_WET },
4778 { Xdoor_1, EL_EM_GATE_1 },
4779 { Xdoor_2, EL_EM_GATE_2 },
4780 { Xdoor_3, EL_EM_GATE_3 },
4781 { Xdoor_4, EL_EM_GATE_4 },
4782 { Xdoor_5, EL_EMC_GATE_5 },
4783 { Xdoor_6, EL_EMC_GATE_6 },
4784 { Xdoor_7, EL_EMC_GATE_7 },
4785 { Xdoor_8, EL_EMC_GATE_8 },
4786 { Xkey_1, EL_EM_KEY_1 },
4787 { Xkey_2, EL_EM_KEY_2 },
4788 { Xkey_3, EL_EM_KEY_3 },
4789 { Xkey_4, EL_EM_KEY_4 },
4790 { Xkey_5, EL_EMC_KEY_5 },
4791 { Xkey_6, EL_EMC_KEY_6 },
4792 { Xkey_7, EL_EMC_KEY_7 },
4793 { Xkey_8, EL_EMC_KEY_8 },
4794 { Xwind_n, EL_BALLOON_SWITCH_UP },
4795 { Xwind_e, EL_BALLOON_SWITCH_RIGHT },
4796 { Xwind_s, EL_BALLOON_SWITCH_DOWN },
4797 { Xwind_w, EL_BALLOON_SWITCH_LEFT },
4798 { Xwind_nesw, EL_BALLOON_SWITCH_ANY },
4799 { Xwind_stop, EL_BALLOON_SWITCH_NONE },
4800 { Xexit, EL_EXIT_CLOSED },
4801 { Xexit_1, EL_EXIT_OPEN },
4802 { Xdynamite, EL_DYNAMITE },
4803 { Xdynamite_1, EL_DYNAMITE_ACTIVE },
4804 { Xbumper, EL_EMC_BUMPER },
4805 { Xwheel, EL_ROBOT_WHEEL },
4806 { Xswitch, EL_UNKNOWN },
4807 { Xsand, EL_QUICKSAND_EMPTY },
4808 { Xsand_stone, EL_QUICKSAND_FULL },
4809 { Xplant, EL_EMC_PLANT },
4810 { Xlenses, EL_EMC_LENSES },
4811 { Xmagnify, EL_EMC_MAGNIFIER },
4812 { Xdripper, EL_UNKNOWN },
4813 { Xfake_blank, EL_INVISIBLE_WALL },
4814 { Xfake_grass, EL_INVISIBLE_SAND },
4815 { Xfake_door_1, EL_EM_GATE_1_GRAY },
4816 { Xfake_door_2, EL_EM_GATE_2_GRAY },
4817 { Xfake_door_3, EL_EM_GATE_3_GRAY },
4818 { Xfake_door_4, EL_EM_GATE_4_GRAY },
4819 { Xfake_door_5, EL_EMC_GATE_5_GRAY },
4820 { Xfake_door_6, EL_EMC_GATE_6_GRAY },
4821 { Xfake_door_7, EL_EMC_GATE_7_GRAY },
4822 { Xfake_door_8, EL_EMC_GATE_8_GRAY },
4823 { Xsteel_1, EL_STEELWALL },
4824 { Xsteel_2, EL_UNKNOWN },
4825 { Xsteel_3, EL_EMC_STEELWALL_1 },
4826 { Xsteel_4, EL_UNKNOWN },
4827 { Xwall_1, EL_WALL },
4828 { Xwall_2, EL_UNKNOWN },
4829 { Xwall_3, EL_UNKNOWN },
4830 { Xwall_4, EL_UNKNOWN },
4831 { Xround_wall_1, EL_WALL_SLIPPERY },
4832 { Xround_wall_2, EL_UNKNOWN },
4833 { Xround_wall_3, EL_UNKNOWN },
4834 { Xround_wall_4, EL_UNKNOWN },
4835 { Xdecor_1, EL_UNKNOWN },
4836 { Xdecor_2, EL_EMC_WALL_6 },
4837 { Xdecor_3, EL_EMC_WALL_4 },
4838 { Xdecor_4, EL_EMC_WALL_5 },
4839 { Xdecor_5, EL_EMC_WALL_7 },
4840 { Xdecor_6, EL_EMC_WALL_8 },
4841 { Xdecor_7, EL_UNKNOWN },
4842 { Xdecor_8, EL_EMC_WALL_1 },
4843 { Xdecor_9, EL_EMC_WALL_2 },
4844 { Xdecor_10, EL_EMC_WALL_3 },
4845 { Xdecor_11, EL_UNKNOWN },
4846 { Xdecor_12, EL_UNKNOWN },
4847 { Xalpha_0, EL_CHAR('0') },
4848 { Xalpha_1, EL_CHAR('1') },
4849 { Xalpha_2, EL_CHAR('2') },
4850 { Xalpha_3, EL_CHAR('3') },
4851 { Xalpha_4, EL_CHAR('4') },
4852 { Xalpha_5, EL_CHAR('5') },
4853 { Xalpha_6, EL_CHAR('6') },
4854 { Xalpha_7, EL_CHAR('7') },
4855 { Xalpha_8, EL_CHAR('8') },
4856 { Xalpha_9, EL_CHAR('9') },
4857 { Xalpha_excla, EL_CHAR('!') },
4858 { Xalpha_quote, EL_CHAR('"') },
4859 { Xalpha_comma, EL_CHAR(',') },
4860 { Xalpha_minus, EL_CHAR('-') },
4861 { Xalpha_perio, EL_CHAR('.') },
4862 { Xalpha_colon, EL_CHAR(':') },
4863 { Xalpha_quest, EL_CHAR('?') },
4864 { Xalpha_a, EL_CHAR('A') },
4865 { Xalpha_b, EL_CHAR('B') },
4866 { Xalpha_c, EL_CHAR('C') },
4867 { Xalpha_d, EL_CHAR('D') },
4868 { Xalpha_e, EL_CHAR('E') },
4869 { Xalpha_f, EL_CHAR('F') },
4870 { Xalpha_g, EL_CHAR('G') },
4871 { Xalpha_h, EL_CHAR('H') },
4872 { Xalpha_i, EL_CHAR('I') },
4873 { Xalpha_j, EL_CHAR('J') },
4874 { Xalpha_k, EL_CHAR('K') },
4875 { Xalpha_l, EL_CHAR('L') },
4876 { Xalpha_m, EL_CHAR('M') },
4877 { Xalpha_n, EL_CHAR('N') },
4878 { Xalpha_o, EL_CHAR('O') },
4879 { Xalpha_p, EL_CHAR('P') },
4880 { Xalpha_q, EL_CHAR('Q') },
4881 { Xalpha_r, EL_CHAR('R') },
4882 { Xalpha_s, EL_CHAR('S') },
4883 { Xalpha_t, EL_CHAR('T') },
4884 { Xalpha_u, EL_CHAR('U') },
4885 { Xalpha_v, EL_CHAR('V') },
4886 { Xalpha_w, EL_CHAR('W') },
4887 { Xalpha_x, EL_CHAR('X') },
4888 { Xalpha_y, EL_CHAR('Y') },
4889 { Xalpha_z, EL_CHAR('Z') },
4890 { Xalpha_arrow_e, EL_CHAR('>') },
4891 { Xalpha_arrow_w, EL_CHAR('<') },
4892 { Xalpha_copyr, EL_CHAR('©') },
4894 { Zplayer, EL_PLAYER_1 },
4895 { Zplayer, EL_PLAYER_2 },
4896 { Zplayer, EL_PLAYER_3 },
4897 { Zplayer, EL_PLAYER_4 },
4899 { ZBORDER, EL_EMC_LEVEL_BORDER },
4904 if (!mapping_initialized)
4908 /* return "Xalpha_quest" for all undefined elements in mapping array */
4909 for (i = 0; i < NUM_FILE_ELEMENTS; i++)
4910 mapping_RND_to_EM[i] = Xalpha_quest;
4912 for (i = 0; mapping_RND_to_EM_list[i].element_rnd != -1; i++)
4913 mapping_RND_to_EM[mapping_RND_to_EM_list[i].element_rnd] =
4914 mapping_RND_to_EM_list[i].element_em;
4916 mapping_initialized = TRUE;
4919 if (element_rnd >= 0 && element_rnd < NUM_FILE_ELEMENTS)
4920 return mapping_RND_to_EM[element_rnd];
4922 Error(ERR_WARN, "invalid RND level element %d", element_rnd);
4927 int map_element_EM_to_RND(int element_em)
4929 static unsigned short mapping_EM_to_RND[TILE_MAX];
4930 static boolean mapping_initialized = FALSE;
4937 em_object_mapping_list[] =
4939 { Xblank, EL_EMPTY },
4940 { Yacid_splash_eB, EL_EMPTY },
4941 { Yacid_splash_wB, EL_EMPTY },
4943 #ifdef EM_ENGINE_BAD_ROLL
4944 { Xstone_force_e, EL_ROCK },
4945 { Xstone_force_w, EL_ROCK },
4946 { Xnut_force_e, EL_NUT },
4947 { Xnut_force_w, EL_NUT },
4948 { Xspring_force_e, EL_SPRING },
4949 { Xspring_force_w, EL_SPRING },
4950 { Xemerald_force_e, EL_EMERALD },
4951 { Xemerald_force_w, EL_EMERALD },
4952 { Xdiamond_force_e, EL_DIAMOND },
4953 { Xdiamond_force_w, EL_DIAMOND },
4954 { Xbomb_force_e, EL_BOMB },
4955 { Xbomb_force_w, EL_BOMB },
4958 { Xstone, EL_ROCK },
4959 { Xstone_pause, EL_ROCK },
4960 { Xstone_fall, EL_ROCK },
4961 { Ystone_s, EL_ROCK },
4962 { Ystone_sB, EL_ROCK },
4963 { Ystone_e, EL_ROCK },
4964 { Ystone_eB, EL_ROCK },
4965 { Ystone_w, EL_ROCK },
4966 { Ystone_wB, EL_ROCK },
4968 { Xnut_pause, EL_NUT },
4969 { Xnut_fall, EL_NUT },
4971 { Ynut_sB, EL_NUT },
4973 { Ynut_eB, EL_NUT },
4975 { Ynut_wB, EL_NUT },
4976 { Xbug_n, EL_BUG_UP },
4977 { Xbug_e, EL_BUG_RIGHT },
4978 { Xbug_s, EL_BUG_DOWN },
4979 { Xbug_w, EL_BUG_LEFT },
4980 { Xbug_gon, EL_BUG_UP },
4981 { Xbug_goe, EL_BUG_RIGHT },
4982 { Xbug_gos, EL_BUG_DOWN },
4983 { Xbug_gow, EL_BUG_LEFT },
4984 { Ybug_n, EL_BUG_UP },
4985 { Ybug_nB, EL_BUG_UP },
4986 { Ybug_e, EL_BUG_RIGHT },
4987 { Ybug_eB, EL_BUG_RIGHT },
4988 { Ybug_s, EL_BUG_DOWN },
4989 { Ybug_sB, EL_BUG_DOWN },
4990 { Ybug_w, EL_BUG_LEFT },
4991 { Ybug_wB, EL_BUG_LEFT },
4992 { Ybug_w_n, EL_BUG_UP },
4993 { Ybug_n_e, EL_BUG_RIGHT },
4994 { Ybug_e_s, EL_BUG_DOWN },
4995 { Ybug_s_w, EL_BUG_LEFT },
4996 { Ybug_e_n, EL_BUG_UP },
4997 { Ybug_s_e, EL_BUG_RIGHT },
4998 { Ybug_w_s, EL_BUG_DOWN },
4999 { Ybug_n_w, EL_BUG_LEFT },
5000 { Ybug_stone, EL_ROCK },
5001 { Ybug_spring, EL_SPRING },
5002 { Xtank_n, EL_SPACESHIP_UP },
5003 { Xtank_e, EL_SPACESHIP_RIGHT },
5004 { Xtank_s, EL_SPACESHIP_DOWN },
5005 { Xtank_w, EL_SPACESHIP_LEFT },
5006 { Xtank_gon, EL_SPACESHIP_UP },
5007 { Xtank_goe, EL_SPACESHIP_RIGHT },
5008 { Xtank_gos, EL_SPACESHIP_DOWN },
5009 { Xtank_gow, EL_SPACESHIP_LEFT },
5010 { Ytank_n, EL_SPACESHIP_UP },
5011 { Ytank_nB, EL_SPACESHIP_UP },
5012 { Ytank_e, EL_SPACESHIP_RIGHT },
5013 { Ytank_eB, EL_SPACESHIP_RIGHT },
5014 { Ytank_s, EL_SPACESHIP_DOWN },
5015 { Ytank_sB, EL_SPACESHIP_DOWN },
5016 { Ytank_w, EL_SPACESHIP_LEFT },
5017 { Ytank_wB, EL_SPACESHIP_LEFT },
5018 { Ytank_w_n, EL_SPACESHIP_UP },
5019 { Ytank_n_e, EL_SPACESHIP_RIGHT },
5020 { Ytank_e_s, EL_SPACESHIP_DOWN },
5021 { Ytank_s_w, EL_SPACESHIP_LEFT },
5022 { Ytank_e_n, EL_SPACESHIP_UP },
5023 { Ytank_s_e, EL_SPACESHIP_RIGHT },
5024 { Ytank_w_s, EL_SPACESHIP_DOWN },
5025 { Ytank_n_w, EL_SPACESHIP_LEFT },
5026 { Ytank_stone, EL_ROCK },
5027 { Ytank_spring, EL_SPRING },
5028 { Xandroid, EL_EMC_ANDROID },
5029 { Xandroid_1_n, EL_EMC_ANDROID_UP },
5030 { Xandroid_2_n, EL_EMC_ANDROID_UP },
5031 { Xandroid_1_e, EL_EMC_ANDROID_RIGHT },
5032 { Xandroid_2_e, EL_EMC_ANDROID_RIGHT },
5033 { Xandroid_1_w, EL_EMC_ANDROID_LEFT },
5034 { Xandroid_2_w, EL_EMC_ANDROID_LEFT },
5035 { Xandroid_1_s, EL_EMC_ANDROID_DOWN },
5036 { Xandroid_2_s, EL_EMC_ANDROID_DOWN },
5037 { Yandroid_n, EL_EMC_ANDROID_UP },
5038 { Yandroid_nB, EL_EMC_ANDROID_UP },
5039 { Yandroid_ne, EL_EMC_ANDROID_RIGHT_UP },
5040 { Yandroid_neB, EL_EMC_ANDROID_RIGHT_UP },
5041 { Yandroid_e, EL_EMC_ANDROID_RIGHT },
5042 { Yandroid_eB, EL_EMC_ANDROID_RIGHT },
5043 { Yandroid_se, EL_EMC_ANDROID_RIGHT_DOWN },
5044 { Yandroid_seB, EL_EMC_ANDROID_RIGHT_DOWN },
5045 { Yandroid_s, EL_EMC_ANDROID_DOWN },
5046 { Yandroid_sB, EL_EMC_ANDROID_DOWN },
5047 { Yandroid_sw, EL_EMC_ANDROID_LEFT_DOWN },
5048 { Yandroid_swB, EL_EMC_ANDROID_LEFT_DOWN },
5049 { Yandroid_w, EL_EMC_ANDROID_LEFT },
5050 { Yandroid_wB, EL_EMC_ANDROID_LEFT },
5051 { Yandroid_nw, EL_EMC_ANDROID_LEFT_UP },
5052 { Yandroid_nwB, EL_EMC_ANDROID_LEFT_UP },
5053 { Xspring, EL_SPRING },
5054 { Xspring_pause, EL_SPRING },
5055 { Xspring_e, EL_SPRING },
5056 { Xspring_w, EL_SPRING },
5057 { Xspring_fall, EL_SPRING },
5058 { Yspring_s, EL_SPRING },
5059 { Yspring_sB, EL_SPRING },
5060 { Yspring_e, EL_SPRING },
5061 { Yspring_eB, EL_SPRING },
5062 { Yspring_w, EL_SPRING },
5063 { Yspring_wB, EL_SPRING },
5064 { Yspring_kill_e, EL_SPRING },
5065 { Yspring_kill_eB, EL_SPRING },
5066 { Yspring_kill_w, EL_SPRING },
5067 { Yspring_kill_wB, EL_SPRING },
5068 { Xeater_n, EL_YAMYAM },
5069 { Xeater_e, EL_YAMYAM },
5070 { Xeater_w, EL_YAMYAM },
5071 { Xeater_s, EL_YAMYAM },
5072 { Yeater_n, EL_YAMYAM },
5073 { Yeater_nB, EL_YAMYAM },
5074 { Yeater_e, EL_YAMYAM },
5075 { Yeater_eB, EL_YAMYAM },
5076 { Yeater_s, EL_YAMYAM },
5077 { Yeater_sB, EL_YAMYAM },
5078 { Yeater_w, EL_YAMYAM },
5079 { Yeater_wB, EL_YAMYAM },
5080 { Yeater_stone, EL_ROCK },
5081 { Yeater_spring, EL_SPRING },
5082 { Xalien, EL_ROBOT },
5083 { Xalien_pause, EL_ROBOT },
5084 { Yalien_n, EL_ROBOT },
5085 { Yalien_nB, EL_ROBOT },
5086 { Yalien_e, EL_ROBOT },
5087 { Yalien_eB, EL_ROBOT },
5088 { Yalien_s, EL_ROBOT },
5089 { Yalien_sB, EL_ROBOT },
5090 { Yalien_w, EL_ROBOT },
5091 { Yalien_wB, EL_ROBOT },
5092 { Yalien_stone, EL_ROCK },
5093 { Yalien_spring, EL_SPRING },
5094 { Xemerald, EL_EMERALD },
5095 { Xemerald_pause, EL_EMERALD },
5096 { Xemerald_fall, EL_EMERALD },
5097 { Xemerald_shine, EL_EMERALD },
5098 { Yemerald_s, EL_EMERALD },
5099 { Yemerald_sB, EL_EMERALD },
5100 { Yemerald_e, EL_EMERALD },
5101 { Yemerald_eB, EL_EMERALD },
5102 { Yemerald_w, EL_EMERALD },
5103 { Yemerald_wB, EL_EMERALD },
5104 { Yemerald_eat, EL_EMERALD },
5105 { Yemerald_stone, EL_ROCK },
5106 { Xdiamond, EL_DIAMOND },
5107 { Xdiamond_pause, EL_DIAMOND },
5108 { Xdiamond_fall, EL_DIAMOND },
5109 { Xdiamond_shine, EL_DIAMOND },
5110 { Ydiamond_s, EL_DIAMOND },
5111 { Ydiamond_sB, EL_DIAMOND },
5112 { Ydiamond_e, EL_DIAMOND },
5113 { Ydiamond_eB, EL_DIAMOND },
5114 { Ydiamond_w, EL_DIAMOND },
5115 { Ydiamond_wB, EL_DIAMOND },
5116 { Ydiamond_eat, EL_DIAMOND },
5117 { Ydiamond_stone, EL_ROCK },
5118 { Xdrip_fall, EL_AMOEBA_DROP },
5119 { Xdrip_stretch, EL_AMOEBA_DROP },
5120 { Xdrip_stretchB, EL_AMOEBA_DROP },
5121 { Xdrip_eat, EL_AMOEBA_DROP },
5122 { Ydrip_s1, EL_AMOEBA_DROP },
5123 { Ydrip_s1B, EL_AMOEBA_DROP },
5124 { Ydrip_s2, EL_AMOEBA_DROP },
5125 { Ydrip_s2B, EL_AMOEBA_DROP },
5127 { Xbomb_pause, EL_BOMB },
5128 { Xbomb_fall, EL_BOMB },
5129 { Ybomb_s, EL_BOMB },
5130 { Ybomb_sB, EL_BOMB },
5131 { Ybomb_e, EL_BOMB },
5132 { Ybomb_eB, EL_BOMB },
5133 { Ybomb_w, EL_BOMB },
5134 { Ybomb_wB, EL_BOMB },
5135 { Ybomb_eat, EL_BOMB },
5136 { Xballoon, EL_BALLOON },
5137 { Yballoon_n, EL_BALLOON },
5138 { Yballoon_nB, EL_BALLOON },
5139 { Yballoon_e, EL_BALLOON },
5140 { Yballoon_eB, EL_BALLOON },
5141 { Yballoon_s, EL_BALLOON },
5142 { Yballoon_sB, EL_BALLOON },
5143 { Yballoon_w, EL_BALLOON },
5144 { Yballoon_wB, EL_BALLOON },
5145 { Xgrass, EL_SAND },
5146 { Ygrass_nB, EL_SAND },
5147 { Ygrass_eB, EL_SAND },
5148 { Ygrass_sB, EL_SAND },
5149 { Ygrass_wB, EL_SAND },
5151 { Ydirt_nB, EL_SAND },
5152 { Ydirt_eB, EL_SAND },
5153 { Ydirt_sB, EL_SAND },
5154 { Ydirt_wB, EL_SAND },
5155 { Xacid_ne, EL_ACID_POOL_TOPRIGHT },
5156 { Xacid_se, EL_ACID_POOL_BOTTOMRIGHT },
5157 { Xacid_s, EL_ACID_POOL_BOTTOM },
5158 { Xacid_sw, EL_ACID_POOL_BOTTOMLEFT },
5159 { Xacid_nw, EL_ACID_POOL_TOPLEFT },
5160 { Xacid_1, EL_ACID },
5161 { Xacid_2, EL_ACID },
5162 { Xacid_3, EL_ACID },
5163 { Xacid_4, EL_ACID },
5164 { Xacid_5, EL_ACID },
5165 { Xacid_6, EL_ACID },
5166 { Xacid_7, EL_ACID },
5167 { Xacid_8, EL_ACID },
5168 { Xball_1, EL_EMC_MAGIC_BALL },
5169 { Xball_1B, EL_EMC_MAGIC_BALL },
5170 { Xball_2, EL_EMC_MAGIC_BALL },
5171 { Xball_2B, EL_EMC_MAGIC_BALL },
5172 { Yball_eat, EL_EMC_MAGIC_BALL },
5173 { Xgrow_ns, EL_EMC_GROW },
5174 { Ygrow_ns_eat, EL_EMC_GROW },
5175 { Xgrow_ew, EL_EMC_GROW },
5176 { Ygrow_ew_eat, EL_EMC_GROW },
5177 { Xwonderwall, EL_MAGIC_WALL },
5178 { XwonderwallB, EL_MAGIC_WALL },
5179 { Xamoeba_1, EL_AMOEBA_WET },
5180 { Xamoeba_2, EL_AMOEBA_WET },
5181 { Xamoeba_3, EL_AMOEBA_WET },
5182 { Xamoeba_4, EL_AMOEBA_WET },
5183 { Xamoeba_5, EL_AMOEBA_WET },
5184 { Xamoeba_6, EL_AMOEBA_WET },
5185 { Xamoeba_7, EL_AMOEBA_WET },
5186 { Xamoeba_8, EL_AMOEBA_WET },
5187 { Xdoor_1, EL_EM_GATE_1 },
5188 { Xdoor_2, EL_EM_GATE_2 },
5189 { Xdoor_3, EL_EM_GATE_3 },
5190 { Xdoor_4, EL_EM_GATE_4 },
5191 { Xdoor_5, EL_EMC_GATE_5 },
5192 { Xdoor_6, EL_EMC_GATE_6 },
5193 { Xdoor_7, EL_EMC_GATE_7 },
5194 { Xdoor_8, EL_EMC_GATE_8 },
5195 { Xkey_1, EL_EM_KEY_1 },
5196 { Xkey_2, EL_EM_KEY_2 },
5197 { Xkey_3, EL_EM_KEY_3 },
5198 { Xkey_4, EL_EM_KEY_4 },
5199 { Xkey_5, EL_EMC_KEY_5 },
5200 { Xkey_6, EL_EMC_KEY_6 },
5201 { Xkey_7, EL_EMC_KEY_7 },
5202 { Xkey_8, EL_EMC_KEY_8 },
5203 { Xwind_n, EL_BALLOON_SWITCH_UP },
5204 { Xwind_e, EL_BALLOON_SWITCH_RIGHT },
5205 { Xwind_s, EL_BALLOON_SWITCH_DOWN },
5206 { Xwind_w, EL_BALLOON_SWITCH_LEFT },
5207 { Xwind_nesw, EL_BALLOON_SWITCH_ANY },
5208 { Xwind_stop, EL_BALLOON_SWITCH_NONE },
5209 { Xexit, EL_EXIT_CLOSED },
5210 { Xexit_1, EL_EXIT_OPEN },
5211 { Xexit_2, EL_EXIT_OPEN },
5212 { Xexit_3, EL_EXIT_OPEN },
5213 { Xdynamite, EL_DYNAMITE },
5214 { Ydynamite_eat, EL_DYNAMITE },
5215 { Xdynamite_1, EL_DYNAMITE_ACTIVE },
5216 { Xdynamite_2, EL_DYNAMITE_ACTIVE },
5217 { Xdynamite_3, EL_DYNAMITE_ACTIVE },
5218 { Xdynamite_4, EL_DYNAMITE_ACTIVE },
5219 { Xbumper, EL_EMC_BUMPER },
5220 { XbumperB, EL_EMC_BUMPER },
5221 { Xwheel, EL_ROBOT_WHEEL },
5222 { XwheelB, EL_ROBOT_WHEEL },
5223 { Xswitch, EL_UNKNOWN },
5224 { XswitchB, EL_UNKNOWN },
5225 { Xsand, EL_QUICKSAND_EMPTY },
5226 { Xsand_stone, EL_QUICKSAND_FULL },
5227 { Xsand_stonein_1, EL_QUICKSAND_FULL },
5228 { Xsand_stonein_2, EL_QUICKSAND_FULL },
5229 { Xsand_stonein_3, EL_QUICKSAND_FULL },
5230 { Xsand_stonein_4, EL_QUICKSAND_FULL },
5231 { Xsand_stonesand_1, EL_QUICKSAND_FULL },
5232 { Xsand_stonesand_2, EL_QUICKSAND_FULL },
5233 { Xsand_stonesand_3, EL_QUICKSAND_FULL },
5234 { Xsand_stonesand_4, EL_QUICKSAND_FULL },
5235 { Xsand_stoneout_1, EL_QUICKSAND_FULL },
5236 { Xsand_stoneout_2, EL_QUICKSAND_FULL },
5237 { Xsand_sandstone_1, EL_QUICKSAND_FULL },
5238 { Xsand_sandstone_2, EL_QUICKSAND_FULL },
5239 { Xsand_sandstone_3, EL_QUICKSAND_FULL },
5240 { Xsand_sandstone_4, EL_QUICKSAND_FULL },
5241 { Xplant, EL_EMC_PLANT },
5242 { Yplant, EL_EMC_PLANT },
5243 { Xlenses, EL_EMC_LENSES },
5244 { Xmagnify, EL_EMC_MAGNIFIER },
5245 { Xdripper, EL_UNKNOWN },
5246 { XdripperB, EL_UNKNOWN },
5247 { Xfake_blank, EL_INVISIBLE_WALL },
5248 { Xfake_blankB, EL_INVISIBLE_WALL },
5249 { Xfake_grass, EL_INVISIBLE_SAND },
5250 { Xfake_grassB, EL_INVISIBLE_SAND },
5251 { Xfake_door_1, EL_EM_GATE_1_GRAY },
5252 { Xfake_door_2, EL_EM_GATE_2_GRAY },
5253 { Xfake_door_3, EL_EM_GATE_3_GRAY },
5254 { Xfake_door_4, EL_EM_GATE_4_GRAY },
5255 { Xfake_door_5, EL_EMC_GATE_5_GRAY },
5256 { Xfake_door_6, EL_EMC_GATE_6_GRAY },
5257 { Xfake_door_7, EL_EMC_GATE_7_GRAY },
5258 { Xfake_door_8, EL_EMC_GATE_8_GRAY },
5259 { Xsteel_1, EL_STEELWALL },
5260 { Xsteel_2, EL_UNKNOWN },
5261 { Xsteel_3, EL_EMC_STEELWALL_1 },
5262 { Xsteel_4, EL_UNKNOWN },
5263 { Xwall_1, EL_WALL },
5264 { Xwall_2, EL_UNKNOWN },
5265 { Xwall_3, EL_UNKNOWN },
5266 { Xwall_4, EL_UNKNOWN },
5267 { Xround_wall_1, EL_WALL_SLIPPERY },
5268 { Xround_wall_2, EL_UNKNOWN },
5269 { Xround_wall_3, EL_UNKNOWN },
5270 { Xround_wall_4, EL_UNKNOWN },
5271 { Xdecor_1, EL_UNKNOWN },
5272 { Xdecor_2, EL_EMC_WALL_6 },
5273 { Xdecor_3, EL_EMC_WALL_4 },
5274 { Xdecor_4, EL_EMC_WALL_5 },
5275 { Xdecor_5, EL_EMC_WALL_7 },
5276 { Xdecor_6, EL_EMC_WALL_8 },
5277 { Xdecor_7, EL_UNKNOWN },
5278 { Xdecor_8, EL_EMC_WALL_1 },
5279 { Xdecor_9, EL_EMC_WALL_2 },
5280 { Xdecor_10, EL_EMC_WALL_3 },
5281 { Xdecor_11, EL_UNKNOWN },
5282 { Xdecor_12, EL_UNKNOWN },
5283 { Xalpha_0, EL_CHAR('0') },
5284 { Xalpha_1, EL_CHAR('1') },
5285 { Xalpha_2, EL_CHAR('2') },
5286 { Xalpha_3, EL_CHAR('3') },
5287 { Xalpha_4, EL_CHAR('4') },
5288 { Xalpha_5, EL_CHAR('5') },
5289 { Xalpha_6, EL_CHAR('6') },
5290 { Xalpha_7, EL_CHAR('7') },
5291 { Xalpha_8, EL_CHAR('8') },
5292 { Xalpha_9, EL_CHAR('9') },
5293 { Xalpha_excla, EL_CHAR('!') },
5294 { Xalpha_quote, EL_CHAR('"') },
5295 { Xalpha_comma, EL_CHAR(',') },
5296 { Xalpha_minus, EL_CHAR('-') },
5297 { Xalpha_perio, EL_CHAR('.') },
5298 { Xalpha_colon, EL_CHAR(':') },
5299 { Xalpha_quest, EL_CHAR('?') },
5300 { Xalpha_a, EL_CHAR('A') },
5301 { Xalpha_b, EL_CHAR('B') },
5302 { Xalpha_c, EL_CHAR('C') },
5303 { Xalpha_d, EL_CHAR('D') },
5304 { Xalpha_e, EL_CHAR('E') },
5305 { Xalpha_f, EL_CHAR('F') },
5306 { Xalpha_g, EL_CHAR('G') },
5307 { Xalpha_h, EL_CHAR('H') },
5308 { Xalpha_i, EL_CHAR('I') },
5309 { Xalpha_j, EL_CHAR('J') },
5310 { Xalpha_k, EL_CHAR('K') },
5311 { Xalpha_l, EL_CHAR('L') },
5312 { Xalpha_m, EL_CHAR('M') },
5313 { Xalpha_n, EL_CHAR('N') },
5314 { Xalpha_o, EL_CHAR('O') },
5315 { Xalpha_p, EL_CHAR('P') },
5316 { Xalpha_q, EL_CHAR('Q') },
5317 { Xalpha_r, EL_CHAR('R') },
5318 { Xalpha_s, EL_CHAR('S') },
5319 { Xalpha_t, EL_CHAR('T') },
5320 { Xalpha_u, EL_CHAR('U') },
5321 { Xalpha_v, EL_CHAR('V') },
5322 { Xalpha_w, EL_CHAR('W') },
5323 { Xalpha_x, EL_CHAR('X') },
5324 { Xalpha_y, EL_CHAR('Y') },
5325 { Xalpha_z, EL_CHAR('Z') },
5326 { Xalpha_arrow_e, EL_CHAR('>') },
5327 { Xalpha_arrow_w, EL_CHAR('<') },
5328 { Xalpha_copyr, EL_CHAR('©') },
5330 { Zplayer, EL_PLAYER_1 },
5332 { ZBORDER, EL_EMC_LEVEL_BORDER },
5337 if (!mapping_initialized)
5341 /* return "EL_UNKNOWN" for all undefined elements in mapping array */
5342 for (i = 0; i < TILE_MAX; i++)
5343 mapping_EM_to_RND[i] = EL_UNKNOWN;
5345 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
5346 mapping_EM_to_RND[em_object_mapping_list[i].element_em] =
5347 em_object_mapping_list[i].element_rnd;
5349 mapping_initialized = TRUE;
5352 if (element_em >= 0 && element_em < TILE_MAX)
5353 return mapping_EM_to_RND[element_em];
5355 Error(ERR_WARN, "invalid EM level element %d", element_em);
5362 int get_next_element(int element)
5366 case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL;
5367 case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY;
5368 case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL;
5369 case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_ACTIVE;
5370 case EL_BD_MAGIC_WALL_FILLING: return EL_BD_MAGIC_WALL_FULL;
5371 case EL_BD_MAGIC_WALL_EMPTYING: return EL_BD_MAGIC_WALL_ACTIVE;
5372 case EL_AMOEBA_DROPPING: return EL_AMOEBA_WET;
5374 default: return element;
5379 int el_act_dir2img(int element, int action, int direction)
5381 element = GFX_ELEMENT(element);
5383 if (direction == MV_NO_MOVING)
5384 return element_info[element].graphic[action];
5386 direction = MV_DIR_BIT(direction);
5388 return element_info[element].direction_graphic[action][direction];
5391 int el_act_dir2img(int element, int action, int direction)
5393 element = GFX_ELEMENT(element);
5394 direction = MV_DIR_BIT(direction); /* default: MV_NO_MOVING => MV_DOWN */
5396 /* direction_graphic[][] == graphic[] for undefined direction graphics */
5397 return element_info[element].direction_graphic[action][direction];
5402 static int el_act_dir2crm(int element, int action, int direction)
5404 element = GFX_ELEMENT(element);
5406 if (direction == MV_NO_MOVING)
5407 return element_info[element].crumbled[action];
5409 direction = MV_DIR_BIT(direction);
5411 return element_info[element].direction_crumbled[action][direction];
5414 static int el_act_dir2crm(int element, int action, int direction)
5416 element = GFX_ELEMENT(element);
5417 direction = MV_DIR_BIT(direction); /* default: MV_NO_MOVING => MV_DOWN */
5419 /* direction_graphic[][] == graphic[] for undefined direction graphics */
5420 return element_info[element].direction_crumbled[action][direction];
5424 int el_act2img(int element, int action)
5426 element = GFX_ELEMENT(element);
5428 return element_info[element].graphic[action];
5431 int el_act2crm(int element, int action)
5433 element = GFX_ELEMENT(element);
5435 return element_info[element].crumbled[action];
5438 int el_dir2img(int element, int direction)
5440 element = GFX_ELEMENT(element);
5442 return el_act_dir2img(element, ACTION_DEFAULT, direction);
5445 int el2baseimg(int element)
5447 return element_info[element].graphic[ACTION_DEFAULT];
5450 int el2img(int element)
5452 element = GFX_ELEMENT(element);
5454 return element_info[element].graphic[ACTION_DEFAULT];
5457 int el2edimg(int element)
5459 element = GFX_ELEMENT(element);
5461 return element_info[element].special_graphic[GFX_SPECIAL_ARG_EDITOR];
5464 int el2preimg(int element)
5466 element = GFX_ELEMENT(element);
5468 return element_info[element].special_graphic[GFX_SPECIAL_ARG_PREVIEW];
5471 int getGameFrameDelay_EM(int native_em_game_frame_delay)
5473 int game_frame_delay_value;
5475 game_frame_delay_value =
5476 (tape.playing && tape.fast_forward ? FfwdFrameDelay :
5477 GameFrameDelay == GAME_FRAME_DELAY ? native_em_game_frame_delay :
5480 if (tape.playing && tape.warp_forward && !tape.pausing)
5481 game_frame_delay_value = 0;
5483 return game_frame_delay_value;
5486 unsigned int InitRND(long seed)
5488 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
5489 return InitEngineRND_EM(seed);
5491 return InitEngineRND(seed);
5494 #define DEBUG_EM_GFX 0
5496 void InitGraphicInfo_EM(void)
5498 struct Mapping_EM_to_RND_object object_mapping[TILE_MAX];
5499 struct Mapping_EM_to_RND_player player_mapping[2][SPR_MAX];
5503 if (graphic_info_em_object[0][0].bitmap == NULL)
5505 /* EM graphics not yet initialized in em_open_all() */
5511 /* always start with reliable default values */
5512 for (i = 0; i < TILE_MAX; i++)
5514 object_mapping[i].element_rnd = EL_UNKNOWN;
5515 object_mapping[i].is_backside = FALSE;
5516 object_mapping[i].action = ACTION_DEFAULT;
5517 object_mapping[i].direction = MV_NO_MOVING;
5520 /* always start with reliable default values */
5521 for (p = 0; p < 2; p++)
5523 for (i = 0; i < SPR_MAX; i++)
5525 player_mapping[p][i].element_rnd = EL_UNKNOWN;
5526 player_mapping[p][i].action = ACTION_DEFAULT;
5527 player_mapping[p][i].direction = MV_NO_MOVING;
5531 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
5533 int e = em_object_mapping_list[i].element_em;
5535 object_mapping[e].element_rnd = em_object_mapping_list[i].element_rnd;
5536 object_mapping[e].is_backside = em_object_mapping_list[i].is_backside;
5538 if (em_object_mapping_list[i].action != -1)
5539 object_mapping[e].action = em_object_mapping_list[i].action;
5541 if (em_object_mapping_list[i].direction != -1)
5542 object_mapping[e].direction = (1 << em_object_mapping_list[i].direction);
5545 for (i = 0; em_player_mapping_list[i].action_em != -1; i++)
5547 int a = em_player_mapping_list[i].action_em;
5548 int p = em_player_mapping_list[i].player_nr;
5550 player_mapping[p][a].element_rnd = em_player_mapping_list[i].element_rnd;
5552 if (em_player_mapping_list[i].action != -1)
5553 player_mapping[p][a].action = em_player_mapping_list[i].action;
5555 if (em_player_mapping_list[i].direction != -1)
5556 player_mapping[p][a].direction =
5557 (1 << em_player_mapping_list[i].direction);
5560 for (i = 0; i < TILE_MAX; i++)
5562 int element = object_mapping[i].element_rnd;
5563 int action = object_mapping[i].action;
5564 int direction = object_mapping[i].direction;
5565 boolean is_backside = object_mapping[i].is_backside;
5566 boolean action_removing = (action == ACTION_DIGGING ||
5567 action == ACTION_SNAPPING ||
5568 action == ACTION_COLLECTING);
5569 boolean action_exploding = ((action == ACTION_EXPLODING ||
5570 action == ACTION_SMASHED_BY_ROCK ||
5571 action == ACTION_SMASHED_BY_SPRING) &&
5572 element != EL_DIAMOND);
5573 boolean action_active = (action == ACTION_ACTIVE);
5574 boolean action_other = (action == ACTION_OTHER);
5576 for (j = 0; j < 8; j++)
5578 int effective_element = (j > 5 && i == Yacid_splash_eB ? EL_EMPTY :
5579 j > 5 && i == Yacid_splash_wB ? EL_EMPTY :
5581 i == Xdrip_stretch ? element :
5582 i == Xdrip_stretchB ? element :
5583 i == Ydrip_s1 ? element :
5584 i == Ydrip_s1B ? element :
5585 i == Xball_1B ? element :
5586 i == Xball_2 ? element :
5587 i == Xball_2B ? element :
5588 i == Yball_eat ? element :
5589 i == Ykey_1_eat ? element :
5590 i == Ykey_2_eat ? element :
5591 i == Ykey_3_eat ? element :
5592 i == Ykey_4_eat ? element :
5593 i == Ykey_5_eat ? element :
5594 i == Ykey_6_eat ? element :
5595 i == Ykey_7_eat ? element :
5596 i == Ykey_8_eat ? element :
5597 i == Ylenses_eat ? element :
5598 i == Ymagnify_eat ? element :
5599 i == Ygrass_eat ? element :
5600 i == Ydirt_eat ? element :
5601 i == Yspring_kill_e ? EL_SPRING :
5602 i == Yspring_kill_w ? EL_SPRING :
5603 i == Yemerald_stone ? EL_EMERALD :
5604 i == Ydiamond_stone ? EL_ROCK :
5605 i == Xsand_stonein_4 ? EL_EMPTY :
5606 i == Xsand_stoneout_2 ? EL_ROCK :
5607 is_backside ? EL_EMPTY :
5608 action_removing ? EL_EMPTY :
5610 int effective_action = (j < 7 ? action :
5611 i == Xdrip_stretch ? action :
5612 i == Xdrip_stretchB ? action :
5613 i == Ydrip_s1 ? action :
5614 i == Ydrip_s1B ? action :
5615 i == Xball_1B ? action :
5616 i == Xball_2 ? action :
5617 i == Xball_2B ? action :
5618 i == Yball_eat ? action :
5619 i == Ykey_1_eat ? action :
5620 i == Ykey_2_eat ? action :
5621 i == Ykey_3_eat ? action :
5622 i == Ykey_4_eat ? action :
5623 i == Ykey_5_eat ? action :
5624 i == Ykey_6_eat ? action :
5625 i == Ykey_7_eat ? action :
5626 i == Ykey_8_eat ? action :
5627 i == Ylenses_eat ? action :
5628 i == Ymagnify_eat ? action :
5629 i == Ygrass_eat ? action :
5630 i == Ydirt_eat ? action :
5631 i == Xsand_stonein_1 ? action :
5632 i == Xsand_stonein_2 ? action :
5633 i == Xsand_stonein_3 ? action :
5634 i == Xsand_stonein_4 ? action :
5635 i == Xsand_stoneout_1 ? action :
5636 i == Xsand_stoneout_2 ? action :
5637 i == Xboom_android ? ACTION_EXPLODING :
5638 action_exploding ? ACTION_EXPLODING :
5639 action_active ? action :
5640 action_other ? action :
5642 int graphic = (el_act_dir2img(effective_element, effective_action,
5644 int crumbled = (el_act_dir2crm(effective_element, effective_action,
5646 int base_graphic = el_act2img(effective_element, ACTION_DEFAULT);
5647 int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT);
5648 boolean has_crumbled_graphics = (base_crumbled != base_graphic);
5649 struct GraphicInfo *g = &graphic_info[graphic];
5650 struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
5653 /* ensure to get symmetric 3-frame, 2-delay animations as used in EM */
5654 boolean special_animation = (action != ACTION_DEFAULT &&
5655 g->anim_frames == 3 &&
5656 g->anim_delay == 2 &&
5657 g->anim_mode & ANIM_LINEAR);
5658 int sync_frame = (i == Xdrip_stretch ? 7 :
5659 i == Xdrip_stretchB ? 7 :
5660 i == Ydrip_s2 ? j + 8 :
5661 i == Ydrip_s2B ? j + 8 :
5670 i == Xfake_acid_1 ? 0 :
5671 i == Xfake_acid_2 ? 10 :
5672 i == Xfake_acid_3 ? 20 :
5673 i == Xfake_acid_4 ? 30 :
5674 i == Xfake_acid_5 ? 40 :
5675 i == Xfake_acid_6 ? 50 :
5676 i == Xfake_acid_7 ? 60 :
5677 i == Xfake_acid_8 ? 70 :
5679 i == Xball_2B ? j + 8 :
5680 i == Yball_eat ? j + 1 :
5681 i == Ykey_1_eat ? j + 1 :
5682 i == Ykey_2_eat ? j + 1 :
5683 i == Ykey_3_eat ? j + 1 :
5684 i == Ykey_4_eat ? j + 1 :
5685 i == Ykey_5_eat ? j + 1 :
5686 i == Ykey_6_eat ? j + 1 :
5687 i == Ykey_7_eat ? j + 1 :
5688 i == Ykey_8_eat ? j + 1 :
5689 i == Ylenses_eat ? j + 1 :
5690 i == Ymagnify_eat ? j + 1 :
5691 i == Ygrass_eat ? j + 1 :
5692 i == Ydirt_eat ? j + 1 :
5693 i == Xamoeba_1 ? 0 :
5694 i == Xamoeba_2 ? 1 :
5695 i == Xamoeba_3 ? 2 :
5696 i == Xamoeba_4 ? 3 :
5697 i == Xamoeba_5 ? 0 :
5698 i == Xamoeba_6 ? 1 :
5699 i == Xamoeba_7 ? 2 :
5700 i == Xamoeba_8 ? 3 :
5701 i == Xexit_2 ? j + 8 :
5702 i == Xexit_3 ? j + 16 :
5703 i == Xdynamite_1 ? 0 :
5704 i == Xdynamite_2 ? 20 :
5705 i == Xdynamite_3 ? 40 :
5706 i == Xdynamite_4 ? 60 :
5707 i == Xsand_stonein_1 ? j + 1 :
5708 i == Xsand_stonein_2 ? j + 9 :
5709 i == Xsand_stonein_3 ? j + 17 :
5710 i == Xsand_stonein_4 ? j + 25 :
5711 i == Xsand_stoneout_1 && j == 0 ? 0 :
5712 i == Xsand_stoneout_1 && j == 1 ? 0 :
5713 i == Xsand_stoneout_1 && j == 2 ? 1 :
5714 i == Xsand_stoneout_1 && j == 3 ? 2 :
5715 i == Xsand_stoneout_1 && j == 4 ? 2 :
5716 i == Xsand_stoneout_1 && j == 5 ? 3 :
5717 i == Xsand_stoneout_1 && j == 6 ? 4 :
5718 i == Xsand_stoneout_1 && j == 7 ? 4 :
5719 i == Xsand_stoneout_2 && j == 0 ? 5 :
5720 i == Xsand_stoneout_2 && j == 1 ? 6 :
5721 i == Xsand_stoneout_2 && j == 2 ? 7 :
5722 i == Xsand_stoneout_2 && j == 3 ? 8 :
5723 i == Xsand_stoneout_2 && j == 4 ? 9 :
5724 i == Xsand_stoneout_2 && j == 5 ? 11 :
5725 i == Xsand_stoneout_2 && j == 6 ? 13 :
5726 i == Xsand_stoneout_2 && j == 7 ? 15 :
5727 i == Xboom_bug && j == 1 ? 2 :
5728 i == Xboom_bug && j == 2 ? 2 :
5729 i == Xboom_bug && j == 3 ? 4 :
5730 i == Xboom_bug && j == 4 ? 4 :
5731 i == Xboom_bug && j == 5 ? 2 :
5732 i == Xboom_bug && j == 6 ? 2 :
5733 i == Xboom_bug && j == 7 ? 0 :
5734 i == Xboom_bomb && j == 1 ? 2 :
5735 i == Xboom_bomb && j == 2 ? 2 :
5736 i == Xboom_bomb && j == 3 ? 4 :
5737 i == Xboom_bomb && j == 4 ? 4 :
5738 i == Xboom_bomb && j == 5 ? 2 :
5739 i == Xboom_bomb && j == 6 ? 2 :
5740 i == Xboom_bomb && j == 7 ? 0 :
5741 i == Xboom_android && j == 7 ? 6 :
5742 i == Xboom_1 && j == 1 ? 2 :
5743 i == Xboom_1 && j == 2 ? 2 :
5744 i == Xboom_1 && j == 3 ? 4 :
5745 i == Xboom_1 && j == 4 ? 4 :
5746 i == Xboom_1 && j == 5 ? 6 :
5747 i == Xboom_1 && j == 6 ? 6 :
5748 i == Xboom_1 && j == 7 ? 8 :
5749 i == Xboom_2 && j == 0 ? 8 :
5750 i == Xboom_2 && j == 1 ? 8 :
5751 i == Xboom_2 && j == 2 ? 10 :
5752 i == Xboom_2 && j == 3 ? 10 :
5753 i == Xboom_2 && j == 4 ? 10 :
5754 i == Xboom_2 && j == 5 ? 12 :
5755 i == Xboom_2 && j == 6 ? 12 :
5756 i == Xboom_2 && j == 7 ? 12 :
5757 special_animation && j == 4 ? 3 :
5758 effective_action != action ? 0 :
5762 Bitmap *debug_bitmap = g_em->bitmap;
5763 int debug_src_x = g_em->src_x;
5764 int debug_src_y = g_em->src_y;
5767 int frame = getAnimationFrame(g->anim_frames,
5770 g->anim_start_frame,
5773 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y,
5774 g->double_movement && is_backside);
5776 g_em->bitmap = src_bitmap;
5777 g_em->src_x = src_x;
5778 g_em->src_y = src_y;
5779 g_em->src_offset_x = 0;
5780 g_em->src_offset_y = 0;
5781 g_em->dst_offset_x = 0;
5782 g_em->dst_offset_y = 0;
5783 g_em->width = TILEX;
5784 g_em->height = TILEY;
5786 g_em->crumbled_bitmap = NULL;
5787 g_em->crumbled_src_x = 0;
5788 g_em->crumbled_src_y = 0;
5789 g_em->crumbled_border_size = 0;
5791 g_em->has_crumbled_graphics = FALSE;
5792 g_em->preserve_background = FALSE;
5795 if (has_crumbled_graphics && crumbled == IMG_EMPTY_SPACE)
5796 printf("::: empty crumbled: %d [%s], %d, %d\n",
5797 effective_element, element_info[effective_element].token_name,
5798 effective_action, direction);
5801 /* if element can be crumbled, but certain action graphics are just empty
5802 space (like snapping sand with the original R'n'D graphics), do not
5803 treat these empty space graphics as crumbled graphics in EMC engine */
5804 if (has_crumbled_graphics && crumbled != IMG_EMPTY_SPACE)
5806 getGraphicSource(crumbled, frame, &src_bitmap, &src_x, &src_y);
5808 g_em->has_crumbled_graphics = TRUE;
5809 g_em->crumbled_bitmap = src_bitmap;
5810 g_em->crumbled_src_x = src_x;
5811 g_em->crumbled_src_y = src_y;
5812 g_em->crumbled_border_size = graphic_info[crumbled].border_size;
5815 if (!g->double_movement && (effective_action == ACTION_FALLING ||
5816 effective_action == ACTION_MOVING ||
5817 effective_action == ACTION_PUSHING))
5820 (effective_action == ACTION_FALLING ? MV_DOWN : direction);
5821 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? 1 : 0);
5822 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? 1 : 0);
5823 int num_steps = (i == Ydrip_s1 ||
5826 i == Ydrip_s2B ? 16 : 8);
5827 int cx = ABS(dx) * (TILEX / num_steps);
5828 int cy = ABS(dy) * (TILEY / num_steps);
5829 int step_frame = (i == Ydrip_s2 ||
5830 i == Ydrip_s2B ? j + 8 : j) + 1;
5831 int step = (is_backside ? step_frame : num_steps - step_frame);
5833 if (is_backside) /* tile where movement starts */
5835 if (dx < 0 || dy < 0)
5837 g_em->src_offset_x = cx * step;
5838 g_em->src_offset_y = cy * step;
5842 g_em->dst_offset_x = cx * step;
5843 g_em->dst_offset_y = cy * step;
5846 else /* tile where movement ends */
5848 if (dx < 0 || dy < 0)
5850 g_em->dst_offset_x = cx * step;
5851 g_em->dst_offset_y = cy * step;
5855 g_em->src_offset_x = cx * step;
5856 g_em->src_offset_y = cy * step;
5860 g_em->width = TILEX - cx * step;
5861 g_em->height = TILEY - cy * step;
5864 /* create unique graphic identifier to decide if tile must be redrawn */
5865 /* bit 31 - 16 (16 bit): EM style element
5866 bit 15 - 12 ( 4 bit): EM style frame
5867 bit 11 - 6 ( 6 bit): graphic width
5868 bit 5 - 0 ( 6 bit): graphic height */
5869 g_em->unique_identifier =
5870 (i << 16) | (j << 12) | (g_em->width << 6) | g_em->height;
5873 if (g_em->bitmap != debug_bitmap ||
5874 g_em->src_x != debug_src_x ||
5875 g_em->src_y != debug_src_y ||
5876 g_em->src_offset_x != 0 ||
5877 g_em->src_offset_y != 0 ||
5878 g_em->dst_offset_x != 0 ||
5879 g_em->dst_offset_y != 0 ||
5880 g_em->width != TILEX ||
5881 g_em->height != TILEY)
5883 static int last_i = -1;
5891 printf("::: EMC GFX ERROR for element %d -> %d ('%s', '%s', %d)",
5892 i, element, element_info[element].token_name,
5893 element_action_info[effective_action].suffix, direction);
5895 if (element != effective_element)
5896 printf(" [%d ('%s')]",
5898 element_info[effective_element].token_name);
5902 if (g_em->bitmap != debug_bitmap)
5903 printf(" %d (%d): different bitmap! (0x%08x != 0x%08x)\n",
5904 j, is_backside, (int)(g_em->bitmap), (int)(debug_bitmap));
5906 if (g_em->src_x != debug_src_x ||
5907 g_em->src_y != debug_src_y)
5908 printf(" frame %d (%c): %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
5909 j, (is_backside ? 'B' : 'F'),
5910 g_em->src_x, g_em->src_y,
5911 g_em->src_x / 32, g_em->src_y / 32,
5912 debug_src_x, debug_src_y,
5913 debug_src_x / 32, debug_src_y / 32);
5915 if (g_em->src_offset_x != 0 ||
5916 g_em->src_offset_y != 0 ||
5917 g_em->dst_offset_x != 0 ||
5918 g_em->dst_offset_y != 0)
5919 printf(" %d (%d): offsets %d,%d and %d,%d should be all 0\n",
5921 g_em->src_offset_x, g_em->src_offset_y,
5922 g_em->dst_offset_x, g_em->dst_offset_y);
5924 if (g_em->width != TILEX ||
5925 g_em->height != TILEY)
5926 printf(" %d (%d): size %d,%d should be %d,%d\n",
5928 g_em->width, g_em->height, TILEX, TILEY);
5935 for (i = 0; i < TILE_MAX; i++)
5937 for (j = 0; j < 8; j++)
5939 int element = object_mapping[i].element_rnd;
5940 int action = object_mapping[i].action;
5942 if (action == ACTION_SMASHED_BY_ROCK &&
5943 element_info[element].graphic[action] ==
5944 element_info[element].graphic[ACTION_DEFAULT])
5946 /* no separate animation for "smashed by rock" -- use rock instead */
5947 struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
5948 struct GraphicInfo_EM *g_xx = &graphic_info_em_object[Ystone_s][7 - j];
5950 g_em->bitmap = g_xx->bitmap;
5951 g_em->src_x = g_xx->src_x;
5952 g_em->src_y = g_xx->src_y;
5953 g_em->src_offset_x = g_xx->src_offset_x;
5954 g_em->src_offset_y = g_xx->src_offset_y;
5955 g_em->dst_offset_x = g_xx->dst_offset_x;
5956 g_em->dst_offset_y = g_xx->dst_offset_y;
5957 g_em->width = g_xx->width;
5958 g_em->height = g_xx->height;
5960 g_em->preserve_background = TRUE;
5965 for (p = 0; p < 2; p++)
5967 for (i = 0; i < SPR_MAX; i++)
5969 int element = player_mapping[p][i].element_rnd;
5970 int action = player_mapping[p][i].action;
5971 int direction = player_mapping[p][i].direction;
5973 for (j = 0; j < 8; j++)
5975 int effective_element = element;
5976 int effective_action = action;
5977 int graphic = (direction == MV_NO_MOVING ?
5978 el_act2img(effective_element, effective_action) :
5979 el_act_dir2img(effective_element, effective_action,
5981 struct GraphicInfo *g = &graphic_info[graphic];
5982 struct GraphicInfo_EM *g_em = &graphic_info_em_player[p][i][7 - j];
5988 Bitmap *debug_bitmap = g_em->bitmap;
5989 int debug_src_x = g_em->src_x;
5990 int debug_src_y = g_em->src_y;
5993 int frame = getAnimationFrame(g->anim_frames,
5996 g->anim_start_frame,
5999 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x,&src_y, FALSE);
6001 g_em->bitmap = src_bitmap;
6002 g_em->src_x = src_x;
6003 g_em->src_y = src_y;
6004 g_em->src_offset_x = 0;
6005 g_em->src_offset_y = 0;
6006 g_em->dst_offset_x = 0;
6007 g_em->dst_offset_y = 0;
6008 g_em->width = TILEX;
6009 g_em->height = TILEY;
6012 if (g_em->bitmap != debug_bitmap ||
6013 g_em->src_x != debug_src_x ||
6014 g_em->src_y != debug_src_y)
6016 static int last_i = -1;
6024 printf("::: EMC GFX ERROR for p/a %d/%d -> %d ('%s', '%s', %d)",
6025 p, i, element, element_info[element].token_name,
6026 element_action_info[effective_action].suffix, direction);
6028 if (element != effective_element)
6029 printf(" [%d ('%s')]",
6031 element_info[effective_element].token_name);
6035 if (g_em->bitmap != debug_bitmap)
6036 printf(" %d: different bitmap! (0x%08x != 0x%08x)\n",
6037 j, (int)(g_em->bitmap), (int)(debug_bitmap));
6039 if (g_em->src_x != debug_src_x ||
6040 g_em->src_y != debug_src_y)
6041 printf(" frame %d: %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
6043 g_em->src_x, g_em->src_y,
6044 g_em->src_x / 32, g_em->src_y / 32,
6045 debug_src_x, debug_src_y,
6046 debug_src_x / 32, debug_src_y / 32);