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(" GfxElement: %d\n", GfxElement[x][y]);
89 printf(" GfxAction: %d\n", GfxAction[x][y]);
90 printf(" GfxFrame: %d\n", GfxFrame[x][y]);
94 void SetDrawtoField(int mode)
96 if (mode == DRAW_BUFFERED && setup.soft_scrolling)
107 drawto_field = fieldbuffer;
109 else /* DRAW_DIRECT, DRAW_BACKBUFFER */
115 BX2 = SCR_FIELDX - 1;
116 BY2 = SCR_FIELDY - 1;
120 drawto_field = (mode == DRAW_DIRECT ? window : backbuffer);
124 void RedrawPlayfield(boolean force_redraw, int x, int y, int width, int height)
126 if (game_status == GAME_MODE_PLAYING &&
127 level.game_engine_type == GAME_ENGINE_TYPE_EM)
129 BlitScreenToBitmap_EM(backbuffer);
131 else if (game_status == GAME_MODE_PLAYING && !game.envelope_active)
137 width = gfx.sxsize + 2 * TILEX;
138 height = gfx.sysize + 2 * TILEY;
141 if (force_redraw || setup.direct_draw)
144 int x1 = (x - SX) / TILEX, y1 = (y - SY) / TILEY;
145 int x2 = (x - SX + width) / TILEX, y2 = (y - SY + height) / TILEY;
147 if (setup.direct_draw)
148 SetDrawtoField(DRAW_BACKBUFFER);
150 for (xx = BX1; xx <= BX2; xx++)
151 for (yy = BY1; yy <= BY2; yy++)
152 if (xx >= x1 && xx <= x2 && yy >= y1 && yy <= y2)
153 DrawScreenField(xx, yy);
156 if (setup.direct_draw)
157 SetDrawtoField(DRAW_DIRECT);
160 if (setup.soft_scrolling)
162 int fx = FX, fy = FY;
164 fx += (ScreenMovDir & (MV_LEFT|MV_RIGHT) ? ScreenGfxPos : 0);
165 fy += (ScreenMovDir & (MV_UP|MV_DOWN) ? ScreenGfxPos : 0);
167 BlitBitmap(fieldbuffer, backbuffer, fx,fy, SXSIZE,SYSIZE, SX,SY);
171 BlitBitmap(drawto, window, x, y, width, height, x, y);
177 DrawBuffer *buffer = (drawto_field == window ? backbuffer : drawto_field);
179 if (setup.direct_draw && game_status == GAME_MODE_PLAYING)
180 redraw_mask &= ~REDRAW_MAIN;
182 if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD)
183 redraw_mask |= REDRAW_FIELD;
185 if (redraw_mask & REDRAW_FIELD)
186 redraw_mask &= ~REDRAW_TILES;
188 if (redraw_mask == REDRAW_NONE)
191 if (global.fps_slowdown && game_status == GAME_MODE_PLAYING)
193 static boolean last_frame_skipped = FALSE;
194 boolean skip_even_when_not_scrolling = TRUE;
195 boolean just_scrolling = (ScreenMovDir != 0);
196 boolean verbose = FALSE;
198 if (global.fps_slowdown_factor > 1 &&
199 (FrameCounter % global.fps_slowdown_factor) &&
200 (just_scrolling || skip_even_when_not_scrolling))
202 redraw_mask &= ~REDRAW_MAIN;
204 last_frame_skipped = TRUE;
207 printf("FRAME SKIPPED\n");
211 if (last_frame_skipped)
212 redraw_mask |= REDRAW_FIELD;
214 last_frame_skipped = FALSE;
217 printf("frame not skipped\n");
221 /* synchronize X11 graphics at this point; if we would synchronize the
222 display immediately after the buffer switching (after the XFlush),
223 this could mean that we have to wait for the graphics to complete,
224 although we could go on doing calculations for the next frame */
228 if (redraw_mask & REDRAW_ALL)
230 BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
234 if (redraw_mask & REDRAW_FIELD)
236 if (game_status != GAME_MODE_PLAYING ||
237 redraw_mask & REDRAW_FROM_BACKBUFFER)
239 BlitBitmap(backbuffer, window,
240 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE, REAL_SX, REAL_SY);
244 int fx = FX, fy = FY;
246 if (setup.soft_scrolling)
248 fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
249 fy += (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
252 if (setup.soft_scrolling ||
253 ABS(ScreenMovPos) + ScrollStepSize == TILEX ||
254 ABS(ScreenMovPos) == ScrollStepSize ||
255 redraw_tiles > REDRAWTILES_THRESHOLD)
257 BlitBitmap(buffer, window, fx, fy, SXSIZE, SYSIZE, SX, SY);
261 printf("redrawing all (ScreenGfxPos == %d) because %s\n",
263 (setup.soft_scrolling ?
264 "setup.soft_scrolling" :
265 ABS(ScreenGfxPos) + ScrollStepSize == TILEX ?
266 "ABS(ScreenGfxPos) + ScrollStepSize == TILEX" :
267 ABS(ScreenGfxPos) == ScrollStepSize ?
268 "ABS(ScreenGfxPos) == ScrollStepSize" :
269 "redraw_tiles > REDRAWTILES_THRESHOLD"));
275 redraw_mask &= ~REDRAW_MAIN;
278 if (redraw_mask & REDRAW_DOORS)
280 if (redraw_mask & REDRAW_DOOR_1)
281 BlitBitmap(backbuffer, window, DX, DY, DXSIZE, DYSIZE, DX, DY);
283 if (redraw_mask & REDRAW_DOOR_2)
284 BlitBitmap(backbuffer, window, VX, VY, VXSIZE, VYSIZE, VX, VY);
286 if (redraw_mask & REDRAW_DOOR_3)
287 BlitBitmap(backbuffer, window, EX, EY, EXSIZE, EYSIZE, EX, EY);
289 redraw_mask &= ~REDRAW_DOORS;
292 if (redraw_mask & REDRAW_MICROLEVEL)
294 BlitBitmap(backbuffer, window, SX, SY + 10 * TILEY, SXSIZE, 7 * TILEY,
295 SX, SY + 10 * TILEY);
297 redraw_mask &= ~REDRAW_MICROLEVEL;
300 if (redraw_mask & REDRAW_TILES)
302 for (x = 0; x < SCR_FIELDX; x++)
303 for (y = 0 ; y < SCR_FIELDY; y++)
304 if (redraw[redraw_x1 + x][redraw_y1 + y])
305 BlitBitmap(buffer, window,
306 FX + x * TILEX, FY + y * TILEY, TILEX, TILEY,
307 SX + x * TILEX, SY + y * TILEY);
310 if (redraw_mask & REDRAW_FPS) /* display frames per second */
315 sprintf(info1, " (only every %d. frame)", global.fps_slowdown_factor);
316 if (!global.fps_slowdown)
319 sprintf(text, "%.1f fps%s", global.frames_per_second, info1);
320 DrawTextExt(window, SX, SY, text, FONT_TEXT_2, BLIT_OPAQUE);
325 for (x = 0; x < MAX_BUF_XSIZE; x++)
326 for (y = 0; y < MAX_BUF_YSIZE; y++)
329 redraw_mask = REDRAW_NONE;
335 long fading_delay = 300;
337 if (setup.fading && (redraw_mask & REDRAW_FIELD))
344 ClearRectangle(window, REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
347 for (i = 0; i < 2 * FULL_SYSIZE; i++)
349 for (y = 0; y < FULL_SYSIZE; y++)
351 BlitBitmap(backbuffer, window,
352 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
360 for (i = 1; i < FULL_SYSIZE; i+=2)
361 BlitBitmap(backbuffer, window,
362 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
368 SetClipOrigin(clip_gc[PIX_FADEMASK], 0, 0);
369 BlitBitmapMasked(backbuffer, window,
370 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
375 SetClipOrigin(clip_gc[PIX_FADEMASK], -1, -1);
376 BlitBitmapMasked(backbuffer, window,
377 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
382 SetClipOrigin(clip_gc[PIX_FADEMASK], 0, -1);
383 BlitBitmapMasked(backbuffer, window,
384 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
389 SetClipOrigin(clip_gc[PIX_FADEMASK], -1, 0);
390 BlitBitmapMasked(backbuffer, window,
391 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
396 redraw_mask &= ~REDRAW_MAIN;
403 void SetMainBackgroundImageIfDefined(int graphic)
405 if (graphic_info[graphic].bitmap)
406 SetMainBackgroundImage(graphic);
409 void SetMainBackgroundImage(int graphic)
411 SetMainBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
412 graphic_info[graphic].bitmap ?
413 graphic_info[graphic].bitmap :
414 graphic_info[IMG_BACKGROUND].bitmap);
417 void SetDoorBackgroundImage(int graphic)
419 SetDoorBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
420 graphic_info[graphic].bitmap ?
421 graphic_info[graphic].bitmap :
422 graphic_info[IMG_BACKGROUND].bitmap);
425 void DrawBackground(int dst_x, int dst_y, int width, int height)
427 ClearRectangleOnBackground(backbuffer, dst_x, dst_y, width, height);
429 redraw_mask |= REDRAW_FIELD;
434 DrawBackground(REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
436 if (setup.soft_scrolling && game_status == GAME_MODE_PLAYING)
438 ClearRectangle(fieldbuffer, 0, 0, FXSIZE, FYSIZE);
439 SetDrawtoField(DRAW_BUFFERED);
442 SetDrawtoField(DRAW_BACKBUFFER);
444 if (setup.direct_draw && game_status == GAME_MODE_PLAYING)
446 ClearRectangle(window, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
447 SetDrawtoField(DRAW_DIRECT);
451 void MarkTileDirty(int x, int y)
453 int xx = redraw_x1 + x;
454 int yy = redraw_y1 + y;
459 redraw[xx][yy] = TRUE;
460 redraw_mask |= REDRAW_TILES;
463 void SetBorderElement()
467 BorderElement = EL_EMPTY;
469 for (y = 0; y < lev_fieldy && BorderElement == EL_EMPTY; y++)
471 for (x = 0; x < lev_fieldx; x++)
473 if (!IS_INDESTRUCTIBLE(Feld[x][y]))
474 BorderElement = EL_STEELWALL;
476 if (y != 0 && y != lev_fieldy - 1 && x != lev_fieldx - 1)
482 void SetRandomAnimationValue(int x, int y)
484 gfx.anim_random_frame = GfxRandom[x][y];
487 inline int getGraphicAnimationFrame(int graphic, int sync_frame)
489 /* animation synchronized with global frame counter, not move position */
490 if (graphic_info[graphic].anim_global_sync || sync_frame < 0)
491 sync_frame = FrameCounter;
493 return getAnimationFrame(graphic_info[graphic].anim_frames,
494 graphic_info[graphic].anim_delay,
495 graphic_info[graphic].anim_mode,
496 graphic_info[graphic].anim_start_frame,
500 inline void getGraphicSourceExt(int graphic, int frame, Bitmap **bitmap,
501 int *x, int *y, boolean get_backside)
503 struct GraphicInfo *g = &graphic_info[graphic];
504 int src_x = g->src_x + (get_backside ? g->offset2_x : 0);
505 int src_y = g->src_y + (get_backside ? g->offset2_y : 0);
509 if (g->offset_y == 0) /* frames are ordered horizontally */
511 int max_width = g->anim_frames_per_line * g->width;
512 int pos = (src_y / g->height) * max_width + src_x + frame * g->offset_x;
514 *x = pos % max_width;
515 *y = src_y % g->height + pos / max_width * g->height;
517 else if (g->offset_x == 0) /* frames are ordered vertically */
519 int max_height = g->anim_frames_per_line * g->height;
520 int pos = (src_x / g->width) * max_height + src_y + frame * g->offset_y;
522 *x = src_x % g->width + pos / max_height * g->width;
523 *y = pos % max_height;
525 else /* frames are ordered diagonally */
527 *x = src_x + frame * g->offset_x;
528 *y = src_y + frame * g->offset_y;
532 void getGraphicSource(int graphic, int frame, Bitmap **bitmap, int *x, int *y)
534 getGraphicSourceExt(graphic, frame, bitmap, x, y, FALSE);
537 void DrawGraphic(int x, int y, int graphic, int frame)
540 if (!IN_SCR_FIELD(x, y))
542 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
543 printf("DrawGraphic(): This should never happen!\n");
548 DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic, frame);
552 void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
558 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
559 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
562 void DrawGraphicThruMask(int x, int y, int graphic, int frame)
565 if (!IN_SCR_FIELD(x, y))
567 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
568 printf("DrawGraphicThruMask(): This should never happen!\n");
573 DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY, graphic,
578 void DrawGraphicThruMaskExt(DrawBuffer *d, int dst_x, int dst_y, int graphic,
584 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
586 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
587 dst_x - src_x, dst_y - src_y);
588 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dst_x, dst_y);
591 void DrawMiniGraphic(int x, int y, int graphic)
593 DrawMiniGraphicExt(drawto, SX + x * MINI_TILEX,SY + y * MINI_TILEY, graphic);
594 MarkTileDirty(x / 2, y / 2);
597 void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
599 struct GraphicInfo *g = &graphic_info[graphic];
601 int mini_starty = g->bitmap->height * 2 / 3;
604 *x = mini_startx + g->src_x / 2;
605 *y = mini_starty + g->src_y / 2;
608 void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
613 getMiniGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
614 BlitBitmap(src_bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
617 inline static void DrawGraphicShiftedNormal(int x, int y, int dx, int dy,
618 int graphic, int frame,
619 int cut_mode, int mask_mode)
624 int width = TILEX, height = TILEY;
627 if (dx || dy) /* shifted graphic */
629 if (x < BX1) /* object enters playfield from the left */
636 else if (x > BX2) /* object enters playfield from the right */
642 else if (x==BX1 && dx < 0) /* object leaves playfield to the left */
648 else if (x==BX2 && dx > 0) /* object leaves playfield to the right */
650 else if (dx) /* general horizontal movement */
651 MarkTileDirty(x + SIGN(dx), y);
653 if (y < BY1) /* object enters playfield from the top */
655 if (cut_mode==CUT_BELOW) /* object completely above top border */
663 else if (y > BY2) /* object enters playfield from the bottom */
669 else if (y==BY1 && dy < 0) /* object leaves playfield to the top */
675 else if (dy > 0 && cut_mode == CUT_ABOVE)
677 if (y == BY2) /* object completely above bottom border */
683 MarkTileDirty(x, y + 1);
684 } /* object leaves playfield to the bottom */
685 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
687 else if (dy) /* general vertical movement */
688 MarkTileDirty(x, y + SIGN(dy));
692 if (!IN_SCR_FIELD(x, y))
694 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
695 printf("DrawGraphicShifted(): This should never happen!\n");
700 if (width > 0 && height > 0)
702 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
707 dst_x = FX + x * TILEX + dx;
708 dst_y = FY + y * TILEY + dy;
710 if (mask_mode == USE_MASKING)
712 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
713 dst_x - src_x, dst_y - src_y);
714 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
718 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
725 inline static void DrawGraphicShiftedDouble(int x, int y, int dx, int dy,
726 int graphic, int frame,
727 int cut_mode, int mask_mode)
732 int width = TILEX, height = TILEY;
735 int x2 = x + SIGN(dx);
736 int y2 = y + SIGN(dy);
737 int anim_frames = graphic_info[graphic].anim_frames;
738 int sync_frame = (dx ? ABS(dx) : ABS(dy)) * anim_frames / TILESIZE;
740 /* re-calculate animation frame for two-tile movement animation */
741 frame = getGraphicAnimationFrame(graphic, sync_frame);
743 if (IN_SCR_FIELD(x1, y1)) /* movement start graphic inside screen area */
745 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, TRUE);
747 dst_x = FX + x1 * TILEX;
748 dst_y = FY + y1 * TILEY;
750 if (mask_mode == USE_MASKING)
752 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
753 dst_x - src_x, dst_y - src_y);
754 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
758 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
761 MarkTileDirty(x1, y1);
764 if (IN_SCR_FIELD(x2, y2)) /* movement end graphic inside screen area */
766 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, FALSE);
768 dst_x = FX + x2 * TILEX;
769 dst_y = FY + y2 * TILEY;
771 if (mask_mode == USE_MASKING)
773 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
774 dst_x - src_x, dst_y - src_y);
775 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
779 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
782 MarkTileDirty(x2, y2);
786 static void DrawGraphicShifted(int x, int y, int dx, int dy,
787 int graphic, int frame,
788 int cut_mode, int mask_mode)
792 DrawGraphic(x, y, graphic, frame);
797 if (graphic_info[graphic].double_movement) /* EM style movement images */
798 DrawGraphicShiftedDouble(x, y, dx, dy, graphic, frame, cut_mode,mask_mode);
800 DrawGraphicShiftedNormal(x, y, dx, dy, graphic, frame, cut_mode,mask_mode);
803 void DrawGraphicShiftedThruMask(int x, int y, int dx, int dy, int graphic,
804 int frame, int cut_mode)
806 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, USE_MASKING);
809 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
810 int cut_mode, int mask_mode)
812 int lx = LEVELX(x), ly = LEVELY(y);
816 if (IN_LEV_FIELD(lx, ly))
818 SetRandomAnimationValue(lx, ly);
820 graphic = el_act_dir2img(element, GfxAction[lx][ly], GfxDir[lx][ly]);
821 frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
823 /* do not use double (EM style) movement graphic when not moving */
824 if (graphic_info[graphic].double_movement && !dx && !dy)
826 graphic = el_act_dir2img(element, ACTION_DEFAULT, GfxDir[lx][ly]);
827 frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
830 else /* border element */
832 graphic = el2img(element);
833 frame = getGraphicAnimationFrame(graphic, -1);
836 if (element == EL_EXPANDABLE_WALL)
838 boolean left_stopped = FALSE, right_stopped = FALSE;
840 if (!IN_LEV_FIELD(lx - 1, ly) || IS_WALL(Feld[lx - 1][ly]))
842 if (!IN_LEV_FIELD(lx + 1, ly) || IS_WALL(Feld[lx + 1][ly]))
843 right_stopped = TRUE;
845 if (left_stopped && right_stopped)
847 else if (left_stopped)
849 graphic = IMG_EXPANDABLE_WALL_GROWING_RIGHT;
850 frame = graphic_info[graphic].anim_frames - 1;
852 else if (right_stopped)
854 graphic = IMG_EXPANDABLE_WALL_GROWING_LEFT;
855 frame = graphic_info[graphic].anim_frames - 1;
860 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
861 else if (mask_mode == USE_MASKING)
862 DrawGraphicThruMask(x, y, graphic, frame);
864 DrawGraphic(x, y, graphic, frame);
867 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
868 int cut_mode, int mask_mode)
870 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
871 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
872 cut_mode, mask_mode);
875 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
878 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
881 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
884 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
887 void DrawLevelElementThruMask(int x, int y, int element)
889 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
892 void DrawLevelFieldThruMask(int x, int y)
894 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
897 #define TILE_GFX_ELEMENT(x, y) \
898 (GfxElement[x][y] != EL_UNDEFINED && Feld[x][y] != EL_EXPLOSION ? \
899 GfxElement[x][y] : Feld[x][y])
901 static void DrawLevelFieldCrumbledSandExt(int x, int y, int graphic, int frame)
905 int sx = SCREENX(x), sy = SCREENY(y);
907 int width, height, cx, cy, i;
908 int crumbled_border_size = graphic_info[graphic].border_size;
909 static int xy[4][2] =
917 if (!IN_LEV_FIELD(x, y))
920 element = TILE_GFX_ELEMENT(x, y);
922 /* crumble field itself */
923 if (GFX_CRUMBLED(element) && !IS_MOVING(x, y))
925 if (!IN_SCR_FIELD(sx, sy))
928 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
930 for (i = 0; i < 4; i++)
932 int xx = x + xy[i][0];
933 int yy = y + xy[i][1];
935 element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
938 /* check if neighbour field is of same type */
939 if (GFX_CRUMBLED(element) && !IS_MOVING(xx, yy))
942 if (i == 1 || i == 2)
944 width = crumbled_border_size;
946 cx = (i == 2 ? TILEX - crumbled_border_size : 0);
952 height = crumbled_border_size;
954 cy = (i == 3 ? TILEY - crumbled_border_size : 0);
957 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
958 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
961 MarkTileDirty(sx, sy);
963 else /* crumble neighbour fields */
965 for (i = 0; i < 4; i++)
967 int xx = x + xy[i][0];
968 int yy = y + xy[i][1];
969 int sxx = sx + xy[i][0];
970 int syy = sy + xy[i][1];
973 if (!IN_LEV_FIELD(xx, yy) ||
974 !IN_SCR_FIELD(sxx, syy) ||
978 element = TILE_GFX_ELEMENT(xx, yy);
980 if (!GFX_CRUMBLED(element))
983 if (!IN_LEV_FIELD(xx, yy) ||
984 !IN_SCR_FIELD(sxx, syy) ||
985 !GFX_CRUMBLED(Feld[xx][yy]) ||
990 graphic = el_act2crm(Feld[xx][yy], ACTION_DEFAULT);
991 crumbled_border_size = graphic_info[graphic].border_size;
993 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
995 if (i == 1 || i == 2)
997 width = crumbled_border_size;
999 cx = (i == 1 ? TILEX - crumbled_border_size : 0);
1005 height = crumbled_border_size;
1007 cy = (i == 0 ? TILEY - crumbled_border_size : 0);
1010 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1011 width, height, FX + sxx * TILEX + cx, FY + syy * TILEY + cy);
1013 MarkTileDirty(sxx, syy);
1018 void DrawLevelFieldCrumbledSand(int x, int y)
1022 if (!IN_LEV_FIELD(x, y))
1025 graphic = el_act2crm(Feld[x][y], ACTION_DEFAULT);
1027 DrawLevelFieldCrumbledSandExt(x, y, graphic, 0);
1030 void DrawLevelFieldCrumbledSandDigging(int x, int y, int direction,
1033 int graphic1 = el_act_dir2img(GfxElement[x][y], ACTION_DIGGING, direction);
1034 int graphic2 = el_act_dir2crm(GfxElement[x][y], ACTION_DIGGING, direction);
1035 int frame1 = getGraphicAnimationFrame(graphic1, step_frame);
1036 int frame2 = getGraphicAnimationFrame(graphic2, step_frame);
1037 int sx = SCREENX(x), sy = SCREENY(y);
1039 DrawGraphic(sx, sy, graphic1, frame1);
1040 DrawLevelFieldCrumbledSandExt(x, y, graphic2, frame2);
1043 void DrawLevelFieldCrumbledSandNeighbours(int x, int y)
1045 int sx = SCREENX(x), sy = SCREENY(y);
1046 static int xy[4][2] =
1055 for (i = 0; i < 4; i++)
1057 int xx = x + xy[i][0];
1058 int yy = y + xy[i][1];
1059 int sxx = sx + xy[i][0];
1060 int syy = sy + xy[i][1];
1062 if (!IN_LEV_FIELD(xx, yy) ||
1063 !IN_SCR_FIELD(sxx, syy) ||
1064 !GFX_CRUMBLED(Feld[xx][yy]) ||
1068 DrawLevelField(xx, yy);
1072 static int getBorderElement(int x, int y)
1076 { EL_STEELWALL_TOPLEFT, EL_INVISIBLE_STEELWALL_TOPLEFT },
1077 { EL_STEELWALL_TOPRIGHT, EL_INVISIBLE_STEELWALL_TOPRIGHT },
1078 { EL_STEELWALL_BOTTOMLEFT, EL_INVISIBLE_STEELWALL_BOTTOMLEFT },
1079 { EL_STEELWALL_BOTTOMRIGHT, EL_INVISIBLE_STEELWALL_BOTTOMRIGHT },
1080 { EL_STEELWALL_VERTICAL, EL_INVISIBLE_STEELWALL_VERTICAL },
1081 { EL_STEELWALL_HORIZONTAL, EL_INVISIBLE_STEELWALL_HORIZONTAL },
1082 { EL_STEELWALL, EL_INVISIBLE_STEELWALL }
1084 int steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
1085 int steel_position = (x == -1 && y == -1 ? 0 :
1086 x == lev_fieldx && y == -1 ? 1 :
1087 x == -1 && y == lev_fieldy ? 2 :
1088 x == lev_fieldx && y == lev_fieldy ? 3 :
1089 x == -1 || x == lev_fieldx ? 4 :
1090 y == -1 || y == lev_fieldy ? 5 : 6);
1092 return border[steel_position][steel_type];
1095 void DrawScreenElement(int x, int y, int element)
1097 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1098 DrawLevelFieldCrumbledSand(LEVELX(x), LEVELY(y));
1101 void DrawLevelElement(int x, int y, int element)
1103 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1104 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1107 void DrawScreenField(int x, int y)
1109 int lx = LEVELX(x), ly = LEVELY(y);
1110 int element, content;
1112 if (!IN_LEV_FIELD(lx, ly))
1114 if (lx < -1 || lx > lev_fieldx || ly < -1 || ly > lev_fieldy)
1117 element = getBorderElement(lx, ly);
1119 DrawScreenElement(x, y, element);
1123 element = Feld[lx][ly];
1124 content = Store[lx][ly];
1126 if (IS_MOVING(lx, ly))
1128 int horiz_move = (MovDir[lx][ly] == MV_LEFT || MovDir[lx][ly] == MV_RIGHT);
1129 boolean cut_mode = NO_CUTTING;
1131 if (element == EL_QUICKSAND_EMPTYING ||
1132 element == EL_MAGIC_WALL_EMPTYING ||
1133 element == EL_BD_MAGIC_WALL_EMPTYING ||
1134 element == EL_AMOEBA_DROPPING)
1135 cut_mode = CUT_ABOVE;
1136 else if (element == EL_QUICKSAND_FILLING ||
1137 element == EL_MAGIC_WALL_FILLING ||
1138 element == EL_BD_MAGIC_WALL_FILLING)
1139 cut_mode = CUT_BELOW;
1141 if (cut_mode == CUT_ABOVE)
1142 DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1144 DrawScreenElement(x, y, EL_EMPTY);
1147 DrawScreenElementShifted(x, y, MovPos[lx][ly], 0, element, NO_CUTTING);
1148 else if (cut_mode == NO_CUTTING)
1149 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], element, cut_mode);
1151 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], content, cut_mode);
1153 if (content == EL_ACID)
1155 int dir = MovDir[lx][ly];
1156 int newlx = lx + (dir == MV_LEFT ? -1 : dir == MV_RIGHT ? +1 : 0);
1157 int newly = ly + (dir == MV_UP ? -1 : dir == MV_DOWN ? +1 : 0);
1159 DrawLevelElementThruMask(newlx, newly, EL_ACID);
1162 else if (IS_BLOCKED(lx, ly))
1167 boolean cut_mode = NO_CUTTING;
1168 int element_old, content_old;
1170 Blocked2Moving(lx, ly, &oldx, &oldy);
1173 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1174 MovDir[oldx][oldy] == MV_RIGHT);
1176 element_old = Feld[oldx][oldy];
1177 content_old = Store[oldx][oldy];
1179 if (element_old == EL_QUICKSAND_EMPTYING ||
1180 element_old == EL_MAGIC_WALL_EMPTYING ||
1181 element_old == EL_BD_MAGIC_WALL_EMPTYING ||
1182 element_old == EL_AMOEBA_DROPPING)
1183 cut_mode = CUT_ABOVE;
1185 DrawScreenElement(x, y, EL_EMPTY);
1188 DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
1190 else if (cut_mode == NO_CUTTING)
1191 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
1194 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
1197 else if (IS_DRAWABLE(element))
1198 DrawScreenElement(x, y, element);
1200 DrawScreenElement(x, y, EL_EMPTY);
1203 void DrawLevelField(int x, int y)
1205 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1206 DrawScreenField(SCREENX(x), SCREENY(y));
1207 else if (IS_MOVING(x, y))
1211 Moving2Blocked(x, y, &newx, &newy);
1212 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1213 DrawScreenField(SCREENX(newx), SCREENY(newy));
1215 else if (IS_BLOCKED(x, y))
1219 Blocked2Moving(x, y, &oldx, &oldy);
1220 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1221 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1225 void DrawMiniElement(int x, int y, int element)
1229 graphic = el2edimg(element);
1230 DrawMiniGraphic(x, y, graphic);
1233 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1235 int x = sx + scroll_x, y = sy + scroll_y;
1237 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1238 DrawMiniElement(sx, sy, EL_EMPTY);
1239 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1240 DrawMiniElement(sx, sy, Feld[x][y]);
1242 DrawMiniGraphic(sx, sy, el2edimg(getBorderElement(x, y)));
1245 void DrawEnvelopeBackground(int envelope_nr, int startx, int starty,
1246 int x, int y, int xsize, int ysize, int font_nr)
1248 int font_width = getFontWidth(font_nr);
1249 int font_height = getFontHeight(font_nr);
1250 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1253 int dst_x = SX + startx + x * font_width;
1254 int dst_y = SY + starty + y * font_height;
1255 int width = graphic_info[graphic].width;
1256 int height = graphic_info[graphic].height;
1257 int inner_width = MAX(width - 2 * font_width, font_width);
1258 int inner_height = MAX(height - 2 * font_height, font_height);
1259 int inner_sx = (width >= 3 * font_width ? font_width : 0);
1260 int inner_sy = (height >= 3 * font_height ? font_height : 0);
1261 boolean draw_masked = graphic_info[graphic].draw_masked;
1263 getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
1265 if (src_bitmap == NULL || width < font_width || height < font_height)
1267 ClearRectangle(drawto, dst_x, dst_y, font_width, font_height);
1271 src_x += (x == 0 ? 0 : x == xsize - 1 ? width - font_width :
1272 inner_sx + (x - 1) * font_width % inner_width);
1273 src_y += (y == 0 ? 0 : y == ysize - 1 ? height - font_height :
1274 inner_sy + (y - 1) * font_height % inner_height);
1278 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1279 dst_x - src_x, dst_y - src_y);
1280 BlitBitmapMasked(src_bitmap, drawto, src_x, src_y, font_width, font_height,
1284 BlitBitmap(src_bitmap, drawto, src_x, src_y, font_width, font_height,
1288 void AnimateEnvelope(int envelope_nr, int anim_mode, int action)
1290 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1291 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
1292 int mask_mode = (src_bitmap != NULL ? BLIT_MASKED : BLIT_ON_BACKGROUND);
1293 boolean ffwd_delay = (tape.playing && tape.fast_forward);
1294 boolean no_delay = (tape.warp_forward);
1295 unsigned long anim_delay = 0;
1296 int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
1297 int anim_delay_value = (no_delay ? 0 : frame_delay_value);
1298 int font_nr = FONT_ENVELOPE_1 + envelope_nr;
1299 int font_width = getFontWidth(font_nr);
1300 int font_height = getFontHeight(font_nr);
1301 int max_xsize = level.envelope_xsize[envelope_nr];
1302 int max_ysize = level.envelope_ysize[envelope_nr];
1303 int xstart = (anim_mode & ANIM_VERTICAL ? max_xsize : 0);
1304 int ystart = (anim_mode & ANIM_HORIZONTAL ? max_ysize : 0);
1305 int xend = max_xsize;
1306 int yend = (anim_mode != ANIM_DEFAULT ? max_ysize : 0);
1307 int xstep = (xstart < xend ? 1 : 0);
1308 int ystep = (ystart < yend || xstep == 0 ? 1 : 0);
1311 for (x = xstart, y = ystart; x <= xend && y <= yend; x += xstep, y += ystep)
1313 int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2;
1314 int ysize = (action == ACTION_CLOSING ? yend - (y - ystart) : y) + 2;
1315 int sx = (SXSIZE - xsize * font_width) / 2;
1316 int sy = (SYSIZE - ysize * font_height) / 2;
1319 SetDrawtoField(DRAW_BUFFERED);
1321 BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
1323 SetDrawtoField(DRAW_BACKBUFFER);
1325 for (yy = 0; yy < ysize; yy++) for (xx = 0; xx < xsize; xx++)
1326 DrawEnvelopeBackground(envelope_nr, sx,sy, xx,yy, xsize, ysize, font_nr);
1328 DrawTextToTextArea(SX + sx + font_width, SY + sy + font_height,
1329 level.envelope_text[envelope_nr], font_nr, max_xsize,
1330 xsize - 2, ysize - 2, mask_mode);
1332 redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
1335 WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
1339 void ShowEnvelope(int envelope_nr)
1341 int element = EL_ENVELOPE_1 + envelope_nr;
1342 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1343 int sound_opening = element_info[element].sound[ACTION_OPENING];
1344 int sound_closing = element_info[element].sound[ACTION_CLOSING];
1345 boolean ffwd_delay = (tape.playing && tape.fast_forward);
1346 boolean no_delay = (tape.warp_forward);
1347 int normal_delay_value = ONE_SECOND_DELAY / (ffwd_delay ? 2 : 1);
1348 int wait_delay_value = (no_delay ? 0 : normal_delay_value);
1349 int anim_mode = graphic_info[graphic].anim_mode;
1350 int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL:
1351 anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode);
1353 game.envelope_active = TRUE; /* needed for RedrawPlayfield() events */
1355 PlaySoundStereo(sound_opening, SOUND_MIDDLE);
1357 if (anim_mode == ANIM_DEFAULT)
1358 AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_OPENING);
1360 AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_OPENING);
1363 Delay(wait_delay_value);
1365 WaitForEventToContinue();
1367 PlaySoundStereo(sound_closing, SOUND_MIDDLE);
1369 if (anim_mode != ANIM_NONE)
1370 AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_CLOSING);
1372 if (anim_mode == ANIM_DEFAULT)
1373 AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_CLOSING);
1375 game.envelope_active = FALSE;
1377 SetDrawtoField(DRAW_BUFFERED);
1379 redraw_mask |= REDRAW_FIELD;
1383 void getMicroGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1385 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
1386 int mini_startx = src_bitmap->width * 3 / 4;
1387 int mini_starty = src_bitmap->height * 2 / 3;
1388 int src_x = mini_startx + graphic_info[graphic].src_x / 8;
1389 int src_y = mini_starty + graphic_info[graphic].src_y / 8;
1391 *bitmap = src_bitmap;
1396 void DrawMicroElement(int xpos, int ypos, int element)
1400 int graphic = el2preimg(element);
1402 getMicroGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1403 BlitBitmap(src_bitmap, drawto, src_x, src_y, MICRO_TILEX, MICRO_TILEY,
1411 SetDrawBackgroundMask(REDRAW_NONE);
1414 for (x = BX1; x <= BX2; x++)
1415 for (y = BY1; y <= BY2; y++)
1416 DrawScreenField(x, y);
1418 redraw_mask |= REDRAW_FIELD;
1421 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1425 for (x = 0; x < size_x; x++)
1426 for (y = 0; y < size_y; y++)
1427 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1429 redraw_mask |= REDRAW_FIELD;
1432 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1436 DrawBackground(xpos, ypos, MICROLEVEL_XSIZE, MICROLEVEL_YSIZE);
1438 if (lev_fieldx < STD_LEV_FIELDX)
1439 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1440 if (lev_fieldy < STD_LEV_FIELDY)
1441 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1443 xpos += MICRO_TILEX;
1444 ypos += MICRO_TILEY;
1446 for (x = -1; x <= STD_LEV_FIELDX; x++)
1448 for (y = -1; y <= STD_LEV_FIELDY; y++)
1450 int lx = from_x + x, ly = from_y + y;
1452 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1453 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1454 level.field[lx][ly]);
1455 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1
1456 && BorderElement != EL_EMPTY)
1457 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1458 getBorderElement(lx, ly));
1462 redraw_mask |= REDRAW_MICROLEVEL;
1465 #define MICROLABEL_EMPTY 0
1466 #define MICROLABEL_LEVEL_NAME 1
1467 #define MICROLABEL_LEVEL_AUTHOR_HEAD 2
1468 #define MICROLABEL_LEVEL_AUTHOR 3
1469 #define MICROLABEL_IMPORTED_FROM_HEAD 4
1470 #define MICROLABEL_IMPORTED_FROM 5
1471 #define MICROLABEL_IMPORTED_BY_HEAD 6
1472 #define MICROLABEL_IMPORTED_BY 7
1474 static void DrawMicroLevelLabelExt(int mode)
1476 char label_text[MAX_OUTPUT_LINESIZE + 1];
1477 int max_len_label_text;
1478 int font_nr = FONT_TEXT_2;
1481 if (mode == MICROLABEL_LEVEL_AUTHOR_HEAD ||
1482 mode == MICROLABEL_IMPORTED_FROM_HEAD ||
1483 mode == MICROLABEL_IMPORTED_BY_HEAD)
1484 font_nr = FONT_TEXT_3;
1486 max_len_label_text = SXSIZE / getFontWidth(font_nr);
1488 for (i = 0; i < max_len_label_text; i++)
1489 label_text[i] = ' ';
1490 label_text[max_len_label_text] = '\0';
1492 if (strlen(label_text) > 0)
1494 int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
1495 int lypos = MICROLABEL2_YPOS;
1497 DrawText(lxpos, lypos, label_text, font_nr);
1501 (mode == MICROLABEL_LEVEL_NAME ? level.name :
1502 mode == MICROLABEL_LEVEL_AUTHOR_HEAD ? "created by" :
1503 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
1504 mode == MICROLABEL_IMPORTED_FROM_HEAD ? "imported from" :
1505 mode == MICROLABEL_IMPORTED_FROM ? leveldir_current->imported_from :
1506 mode == MICROLABEL_IMPORTED_BY_HEAD ? "imported by" :
1507 mode == MICROLABEL_IMPORTED_BY ? leveldir_current->imported_by :""),
1508 max_len_label_text);
1509 label_text[max_len_label_text] = '\0';
1511 if (strlen(label_text) > 0)
1513 int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
1514 int lypos = MICROLABEL2_YPOS;
1516 DrawText(lxpos, lypos, label_text, font_nr);
1519 redraw_mask |= REDRAW_MICROLEVEL;
1522 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1524 static unsigned long scroll_delay = 0;
1525 static unsigned long label_delay = 0;
1526 static int from_x, from_y, scroll_direction;
1527 static int label_state, label_counter;
1528 int last_game_status = game_status; /* save current game status */
1530 /* force PREVIEW font on preview level */
1531 game_status = GAME_MODE_PSEUDO_PREVIEW;
1535 from_x = from_y = 0;
1536 scroll_direction = MV_RIGHT;
1540 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1541 DrawMicroLevelLabelExt(label_state);
1543 /* initialize delay counters */
1544 DelayReached(&scroll_delay, 0);
1545 DelayReached(&label_delay, 0);
1547 if (leveldir_current->name)
1549 char label_text[MAX_OUTPUT_LINESIZE + 1];
1550 int font_nr = FONT_TEXT_1;
1551 int max_len_label_text = SXSIZE / getFontWidth(font_nr);
1554 strncpy(label_text, leveldir_current->name, max_len_label_text);
1555 label_text[max_len_label_text] = '\0';
1557 lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
1558 lypos = SY + MICROLABEL1_YPOS;
1560 DrawText(lxpos, lypos, label_text, font_nr);
1563 game_status = last_game_status; /* restore current game status */
1568 /* scroll micro level, if needed */
1569 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1570 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1572 switch (scroll_direction)
1578 scroll_direction = MV_UP;
1582 if (from_x < lev_fieldx - STD_LEV_FIELDX)
1585 scroll_direction = MV_DOWN;
1592 scroll_direction = MV_RIGHT;
1596 if (from_y < lev_fieldy - STD_LEV_FIELDY)
1599 scroll_direction = MV_LEFT;
1606 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1609 /* !!! THIS ALL SUCKS -- SHOULD BE CLEANLY REWRITTEN !!! */
1610 /* redraw micro level label, if needed */
1611 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1612 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1613 strcmp(level.author, leveldir_current->name) != 0 &&
1614 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1616 int max_label_counter = 23;
1618 if (leveldir_current->imported_from != NULL &&
1619 strlen(leveldir_current->imported_from) > 0)
1620 max_label_counter += 14;
1621 if (leveldir_current->imported_by != NULL &&
1622 strlen(leveldir_current->imported_by) > 0)
1623 max_label_counter += 14;
1625 label_counter = (label_counter + 1) % max_label_counter;
1626 label_state = (label_counter >= 0 && label_counter <= 7 ?
1627 MICROLABEL_LEVEL_NAME :
1628 label_counter >= 9 && label_counter <= 12 ?
1629 MICROLABEL_LEVEL_AUTHOR_HEAD :
1630 label_counter >= 14 && label_counter <= 21 ?
1631 MICROLABEL_LEVEL_AUTHOR :
1632 label_counter >= 23 && label_counter <= 26 ?
1633 MICROLABEL_IMPORTED_FROM_HEAD :
1634 label_counter >= 28 && label_counter <= 35 ?
1635 MICROLABEL_IMPORTED_FROM :
1636 label_counter >= 37 && label_counter <= 40 ?
1637 MICROLABEL_IMPORTED_BY_HEAD :
1638 label_counter >= 42 && label_counter <= 49 ?
1639 MICROLABEL_IMPORTED_BY : MICROLABEL_EMPTY);
1641 if (leveldir_current->imported_from == NULL &&
1642 (label_state == MICROLABEL_IMPORTED_FROM_HEAD ||
1643 label_state == MICROLABEL_IMPORTED_FROM))
1644 label_state = (label_state == MICROLABEL_IMPORTED_FROM_HEAD ?
1645 MICROLABEL_IMPORTED_BY_HEAD : MICROLABEL_IMPORTED_BY);
1647 DrawMicroLevelLabelExt(label_state);
1650 game_status = last_game_status; /* restore current game status */
1653 inline void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
1654 int graphic, int sync_frame, int mask_mode)
1656 int frame = getGraphicAnimationFrame(graphic, sync_frame);
1658 if (mask_mode == USE_MASKING)
1659 DrawGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
1661 DrawGraphicExt(dst_bitmap, x, y, graphic, frame);
1664 inline void DrawGraphicAnimation(int x, int y, int graphic)
1666 int lx = LEVELX(x), ly = LEVELY(y);
1668 if (!IN_SCR_FIELD(x, y))
1671 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
1672 graphic, GfxFrame[lx][ly], NO_MASKING);
1673 MarkTileDirty(x, y);
1676 void DrawLevelGraphicAnimation(int x, int y, int graphic)
1678 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
1681 void DrawLevelElementAnimation(int x, int y, int element)
1683 int graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
1685 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
1688 inline void DrawLevelGraphicAnimationIfNeeded(int x, int y, int graphic)
1690 int sx = SCREENX(x), sy = SCREENY(y);
1692 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
1695 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
1698 DrawGraphicAnimation(sx, sy, graphic);
1700 if (GFX_CRUMBLED(Feld[x][y]))
1701 DrawLevelFieldCrumbledSand(x, y);
1704 void DrawLevelElementAnimationIfNeeded(int x, int y, int element)
1706 int sx = SCREENX(x), sy = SCREENY(y);
1709 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
1712 graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
1714 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
1717 DrawGraphicAnimation(sx, sy, graphic);
1719 if (GFX_CRUMBLED(element))
1720 DrawLevelFieldCrumbledSand(x, y);
1723 static int getPlayerGraphic(struct PlayerInfo *player, int move_dir)
1725 if (player->use_murphy_graphic)
1727 /* this works only because currently only one player can be "murphy" ... */
1728 static int last_horizontal_dir = MV_LEFT;
1729 int graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, move_dir);
1731 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
1732 last_horizontal_dir = move_dir;
1734 if (graphic == IMG_SP_MURPHY) /* undefined => use special graphic */
1736 int direction = (player->is_snapping ? move_dir : last_horizontal_dir);
1738 graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, direction);
1744 return el_act_dir2img(player->element_nr, player->GfxAction, move_dir);
1747 static boolean equalGraphics(int graphic1, int graphic2)
1749 struct GraphicInfo *g1 = &graphic_info[graphic1];
1750 struct GraphicInfo *g2 = &graphic_info[graphic2];
1752 return (g1->bitmap == g2->bitmap &&
1753 g1->src_x == g2->src_x &&
1754 g1->src_y == g2->src_y &&
1755 g1->anim_frames == g2->anim_frames &&
1756 g1->anim_delay == g2->anim_delay &&
1757 g1->anim_mode == g2->anim_mode);
1760 void DrawAllPlayers()
1764 for (i = 0; i < MAX_PLAYERS; i++)
1765 if (stored_player[i].active)
1766 DrawPlayer(&stored_player[i]);
1769 void DrawPlayerField(int x, int y)
1771 if (!IS_PLAYER(x, y))
1774 DrawPlayer(PLAYERINFO(x, y));
1777 void DrawPlayer(struct PlayerInfo *player)
1779 int jx = player->jx;
1780 int jy = player->jy;
1781 int move_dir = player->MovDir;
1782 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? +1 : 0);
1783 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? +1 : 0);
1784 int last_jx = (player->is_moving ? jx - dx : jx);
1785 int last_jy = (player->is_moving ? jy - dy : jy);
1786 int next_jx = jx + dx;
1787 int next_jy = jy + dy;
1788 boolean player_is_moving = (player->MovPos ? TRUE : FALSE);
1789 int sx = SCREENX(jx), sy = SCREENY(jy);
1790 int sxx = 0, syy = 0;
1791 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
1793 int action = ACTION_DEFAULT;
1794 int last_player_graphic = getPlayerGraphic(player, move_dir);
1795 int last_player_frame = player->Frame;
1798 if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
1802 if (!IN_LEV_FIELD(jx, jy))
1804 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
1805 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
1806 printf("DrawPlayerField(): This should never happen!\n");
1811 if (element == EL_EXPLOSION)
1814 action = (player->is_pushing ? ACTION_PUSHING :
1815 player->is_digging ? ACTION_DIGGING :
1816 player->is_collecting ? ACTION_COLLECTING :
1817 player->is_moving ? ACTION_MOVING :
1818 player->is_snapping ? ACTION_SNAPPING :
1819 player->is_dropping ? ACTION_DROPPING :
1820 player->is_waiting ? player->action_waiting : ACTION_DEFAULT);
1822 InitPlayerGfxAnimation(player, action, move_dir);
1824 /* ----------------------------------------------------------------------- */
1825 /* draw things in the field the player is leaving, if needed */
1826 /* ----------------------------------------------------------------------- */
1828 if (player->is_moving)
1830 if (Back[last_jx][last_jy] && IS_DRAWABLE(last_element))
1832 DrawLevelElement(last_jx, last_jy, Back[last_jx][last_jy]);
1834 if (last_element == EL_DYNAMITE_ACTIVE ||
1835 last_element == EL_SP_DISK_RED_ACTIVE)
1836 DrawDynamite(last_jx, last_jy);
1838 DrawLevelFieldThruMask(last_jx, last_jy);
1840 else if (last_element == EL_DYNAMITE_ACTIVE ||
1841 last_element == EL_SP_DISK_RED_ACTIVE)
1842 DrawDynamite(last_jx, last_jy);
1844 DrawLevelField(last_jx, last_jy);
1846 if (player->is_pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
1847 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
1850 if (!IN_SCR_FIELD(sx, sy))
1853 if (setup.direct_draw)
1854 SetDrawtoField(DRAW_BUFFERED);
1856 /* ----------------------------------------------------------------------- */
1857 /* draw things behind the player, if needed */
1858 /* ----------------------------------------------------------------------- */
1861 DrawLevelElement(jx, jy, Back[jx][jy]);
1862 else if (IS_ACTIVE_BOMB(element))
1863 DrawLevelElement(jx, jy, EL_EMPTY);
1866 if (player_is_moving && GfxElement[jx][jy] != EL_UNDEFINED)
1868 if (GFX_CRUMBLED(GfxElement[jx][jy]))
1869 DrawLevelFieldCrumbledSandDigging(jx, jy, move_dir, player->StepFrame);
1872 int old_element = GfxElement[jx][jy];
1873 int old_graphic = el_act_dir2img(old_element, action, move_dir);
1874 int frame = getGraphicAnimationFrame(old_graphic, player->StepFrame);
1876 DrawGraphic(sx, sy, old_graphic, frame);
1881 GfxElement[jx][jy] = EL_UNDEFINED;
1883 DrawLevelField(jx, jy);
1887 /* ----------------------------------------------------------------------- */
1888 /* draw player himself */
1889 /* ----------------------------------------------------------------------- */
1891 graphic = getPlayerGraphic(player, move_dir);
1893 /* in the case of changed player action or direction, prevent the current
1894 animation frame from being restarted for identical animations */
1895 if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic))
1896 player->Frame = last_player_frame;
1898 frame = getGraphicAnimationFrame(graphic, player->Frame);
1902 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
1903 sxx = player->GfxPos;
1905 syy = player->GfxPos;
1908 if (!setup.soft_scrolling && ScreenMovPos)
1911 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
1913 if (SHIELD_ON(player))
1915 int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
1916 IMG_SHIELD_NORMAL_ACTIVE);
1917 int frame = getGraphicAnimationFrame(graphic, -1);
1919 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
1922 /* ----------------------------------------------------------------------- */
1923 /* draw things the player is pushing, if needed */
1924 /* ----------------------------------------------------------------------- */
1927 printf("::: %d, %d [%d, %d] [%d]\n",
1928 player->is_pushing, player_is_moving, player->GfxAction,
1929 player->is_moving, player_is_moving);
1932 if (player->is_pushing && player->is_moving)
1934 int px = SCREENX(jx), py = SCREENY(jy);
1935 int pxx = (TILEX - ABS(sxx)) * dx;
1936 int pyy = (TILEY - ABS(syy)) * dy;
1941 if (!IS_MOVING(jx, jy)) /* push movement already finished */
1942 element = Feld[next_jx][next_jy];
1944 graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
1945 frame = getGraphicAnimationFrame(graphic, player->StepFrame);
1947 /* draw background element under pushed element (like the Sokoban field) */
1948 if (Back[next_jx][next_jy])
1949 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
1951 /* masked drawing is needed for EMC style (double) movement graphics */
1952 DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame, NO_CUTTING);
1955 /* ----------------------------------------------------------------------- */
1956 /* draw things in front of player (active dynamite or dynabombs) */
1957 /* ----------------------------------------------------------------------- */
1959 if (IS_ACTIVE_BOMB(element))
1961 graphic = el2img(element);
1962 frame = getGraphicAnimationFrame(graphic, GfxFrame[jx][jy]);
1964 if (game.emulation == EMU_SUPAPLEX)
1965 DrawGraphic(sx, sy, IMG_SP_DISK_RED, frame);
1967 DrawGraphicThruMask(sx, sy, graphic, frame);
1970 if (player_is_moving && last_element == EL_EXPLOSION)
1972 int graphic = el_act2img(GfxElement[last_jx][last_jy], ACTION_EXPLODING);
1973 int delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2);
1974 int phase = ExplodePhase[last_jx][last_jy] - 1;
1975 int frame = getGraphicAnimationFrame(graphic, phase - delay);
1978 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy), graphic, frame);
1981 /* ----------------------------------------------------------------------- */
1982 /* draw elements the player is just walking/passing through/under */
1983 /* ----------------------------------------------------------------------- */
1985 if (player_is_moving)
1987 /* handle the field the player is leaving ... */
1988 if (IS_ACCESSIBLE_INSIDE(last_element))
1989 DrawLevelField(last_jx, last_jy);
1990 else if (IS_ACCESSIBLE_UNDER(last_element))
1991 DrawLevelFieldThruMask(last_jx, last_jy);
1994 /* do not redraw accessible elements if the player is just pushing them */
1995 if (!player_is_moving || !player->is_pushing)
1997 /* ... and the field the player is entering */
1998 if (IS_ACCESSIBLE_INSIDE(element))
1999 DrawLevelField(jx, jy);
2000 else if (IS_ACCESSIBLE_UNDER(element))
2001 DrawLevelFieldThruMask(jx, jy);
2004 if (setup.direct_draw)
2006 int dst_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
2007 int dst_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
2008 int x_size = TILEX * (1 + ABS(jx - last_jx));
2009 int y_size = TILEY * (1 + ABS(jy - last_jy));
2011 BlitBitmap(drawto_field, window,
2012 dst_x, dst_y, x_size, y_size, dst_x, dst_y);
2013 SetDrawtoField(DRAW_DIRECT);
2016 MarkTileDirty(sx, sy);
2019 /* ------------------------------------------------------------------------- */
2021 void WaitForEventToContinue()
2023 boolean still_wait = TRUE;
2025 /* simulate releasing mouse button over last gadget, if still pressed */
2027 HandleGadgets(-1, -1, 0);
2029 button_status = MB_RELEASED;
2041 case EVENT_BUTTONPRESS:
2042 case EVENT_KEYPRESS:
2046 case EVENT_KEYRELEASE:
2047 ClearPlayerAction();
2051 HandleOtherEvents(&event);
2055 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2062 /* don't eat all CPU time */
2067 #define MAX_REQUEST_LINES 13
2068 #define MAX_REQUEST_LINE_FONT1_LEN 7
2069 #define MAX_REQUEST_LINE_FONT2_LEN 10
2071 boolean Request(char *text, unsigned int req_state)
2073 int mx, my, ty, result = -1;
2074 unsigned int old_door_state;
2075 int last_game_status = game_status; /* save current game status */
2076 int max_request_line_len = MAX_REQUEST_LINE_FONT1_LEN;
2077 int font_nr = FONT_TEXT_2;
2078 int max_word_len = 0;
2081 for (text_ptr = text; *text_ptr; text_ptr++)
2083 max_word_len = (*text_ptr != ' ' ? max_word_len + 1 : 0);
2085 if (max_word_len > MAX_REQUEST_LINE_FONT1_LEN)
2087 max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
2088 font_nr = FONT_LEVEL_NUMBER;
2094 if (game_status == GAME_MODE_PLAYING &&
2095 level.game_engine_type == GAME_ENGINE_TYPE_EM)
2096 BlitScreenToBitmap_EM(backbuffer);
2098 /* disable deactivated drawing when quick-loading level tape recording */
2099 if (tape.playing && tape.deactivate_display)
2100 TapeDeactivateDisplayOff(TRUE);
2102 SetMouseCursor(CURSOR_DEFAULT);
2104 #if defined(NETWORK_AVALIABLE)
2105 /* pause network game while waiting for request to answer */
2106 if (options.network &&
2107 game_status == GAME_MODE_PLAYING &&
2108 req_state & REQUEST_WAIT_FOR_INPUT)
2109 SendToServer_PausePlaying();
2112 old_door_state = GetDoorState();
2114 /* simulate releasing mouse button over last gadget, if still pressed */
2116 HandleGadgets(-1, -1, 0);
2120 if (old_door_state & DOOR_OPEN_1)
2122 CloseDoor(DOOR_CLOSE_1);
2124 /* save old door content */
2125 BlitBitmap(bitmap_db_door, bitmap_db_door,
2126 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
2127 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
2130 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
2132 /* clear door drawing field */
2133 DrawBackground(DX, DY, DXSIZE, DYSIZE);
2135 /* force DOOR font on preview level */
2136 game_status = GAME_MODE_PSEUDO_DOOR;
2138 /* write text for request */
2139 for (ty = 0; ty < MAX_REQUEST_LINES; ty++)
2141 char text_line[max_request_line_len + 1];
2147 for (tl = 0, tx = 0; tx < max_request_line_len; tl++, tx++)
2150 if (!tc || tc == ' ')
2161 strncpy(text_line, text, tl);
2164 DrawText(DX + (DXSIZE - tl * getFontWidth(font_nr)) / 2,
2165 DY + 8 + ty * (getFontHeight(font_nr) + 2),
2166 text_line, font_nr);
2168 text += tl + (tc == ' ' ? 1 : 0);
2171 game_status = last_game_status; /* restore current game status */
2173 if (req_state & REQ_ASK)
2175 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
2176 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
2178 else if (req_state & REQ_CONFIRM)
2180 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
2182 else if (req_state & REQ_PLAYER)
2184 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
2185 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
2186 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
2187 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
2190 /* copy request gadgets to door backbuffer */
2191 BlitBitmap(drawto, bitmap_db_door,
2192 DX, DY, DXSIZE, DYSIZE,
2193 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2195 OpenDoor(DOOR_OPEN_1);
2197 if (!(req_state & REQUEST_WAIT_FOR_INPUT))
2199 SetDrawBackgroundMask(REDRAW_FIELD);
2204 if (game_status != GAME_MODE_MAIN)
2207 button_status = MB_RELEASED;
2209 request_gadget_id = -1;
2211 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
2223 case EVENT_BUTTONPRESS:
2224 case EVENT_BUTTONRELEASE:
2225 case EVENT_MOTIONNOTIFY:
2227 if (event.type == EVENT_MOTIONNOTIFY)
2229 if (!PointerInWindow(window))
2230 continue; /* window and pointer are on different screens */
2235 motion_status = TRUE;
2236 mx = ((MotionEvent *) &event)->x;
2237 my = ((MotionEvent *) &event)->y;
2241 motion_status = FALSE;
2242 mx = ((ButtonEvent *) &event)->x;
2243 my = ((ButtonEvent *) &event)->y;
2244 if (event.type == EVENT_BUTTONPRESS)
2245 button_status = ((ButtonEvent *) &event)->button;
2247 button_status = MB_RELEASED;
2250 /* this sets 'request_gadget_id' */
2251 HandleGadgets(mx, my, button_status);
2253 switch(request_gadget_id)
2255 case TOOL_CTRL_ID_YES:
2258 case TOOL_CTRL_ID_NO:
2261 case TOOL_CTRL_ID_CONFIRM:
2262 result = TRUE | FALSE;
2265 case TOOL_CTRL_ID_PLAYER_1:
2268 case TOOL_CTRL_ID_PLAYER_2:
2271 case TOOL_CTRL_ID_PLAYER_3:
2274 case TOOL_CTRL_ID_PLAYER_4:
2285 case EVENT_KEYPRESS:
2286 switch(GetEventKey((KeyEvent *)&event, TRUE))
2299 if (req_state & REQ_PLAYER)
2303 case EVENT_KEYRELEASE:
2304 ClearPlayerAction();
2308 HandleOtherEvents(&event);
2312 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2314 int joy = AnyJoystick();
2316 if (joy & JOY_BUTTON_1)
2318 else if (joy & JOY_BUTTON_2)
2324 /* don't eat all CPU time */
2328 if (game_status != GAME_MODE_MAIN)
2333 if (!(req_state & REQ_STAY_OPEN))
2335 CloseDoor(DOOR_CLOSE_1);
2337 if (((old_door_state & DOOR_OPEN_1) && !(req_state & REQ_STAY_CLOSED)) ||
2338 (req_state & REQ_REOPEN))
2339 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
2344 SetDrawBackgroundMask(REDRAW_FIELD);
2346 #if defined(NETWORK_AVALIABLE)
2347 /* continue network game after request */
2348 if (options.network &&
2349 game_status == GAME_MODE_PLAYING &&
2350 req_state & REQUEST_WAIT_FOR_INPUT)
2351 SendToServer_ContinuePlaying();
2354 /* restore deactivated drawing when quick-loading level tape recording */
2355 if (tape.playing && tape.deactivate_display)
2356 TapeDeactivateDisplayOn();
2361 unsigned int OpenDoor(unsigned int door_state)
2363 if (door_state & DOOR_COPY_BACK)
2365 if (door_state & DOOR_OPEN_1)
2366 BlitBitmap(bitmap_db_door, bitmap_db_door,
2367 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
2368 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2370 if (door_state & DOOR_OPEN_2)
2371 BlitBitmap(bitmap_db_door, bitmap_db_door,
2372 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY2, VXSIZE, VYSIZE,
2373 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2375 door_state &= ~DOOR_COPY_BACK;
2378 return MoveDoor(door_state);
2381 unsigned int CloseDoor(unsigned int door_state)
2383 unsigned int old_door_state = GetDoorState();
2385 if (!(door_state & DOOR_NO_COPY_BACK))
2387 if (old_door_state & DOOR_OPEN_1)
2388 BlitBitmap(backbuffer, bitmap_db_door,
2389 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2391 if (old_door_state & DOOR_OPEN_2)
2392 BlitBitmap(backbuffer, bitmap_db_door,
2393 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2395 door_state &= ~DOOR_NO_COPY_BACK;
2398 return MoveDoor(door_state);
2401 unsigned int GetDoorState()
2403 return MoveDoor(DOOR_GET_STATE);
2406 unsigned int SetDoorState(unsigned int door_state)
2408 return MoveDoor(door_state | DOOR_SET_STATE);
2411 unsigned int MoveDoor(unsigned int door_state)
2413 static int door1 = DOOR_OPEN_1;
2414 static int door2 = DOOR_CLOSE_2;
2415 unsigned long door_delay = 0;
2416 unsigned long door_delay_value;
2419 if (door_state == DOOR_GET_STATE)
2420 return(door1 | door2);
2422 if (door_state & DOOR_SET_STATE)
2424 if (door_state & DOOR_ACTION_1)
2425 door1 = door_state & DOOR_ACTION_1;
2426 if (door_state & DOOR_ACTION_2)
2427 door2 = door_state & DOOR_ACTION_2;
2429 return(door1 | door2);
2432 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2433 door_state &= ~DOOR_OPEN_1;
2434 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2435 door_state &= ~DOOR_CLOSE_1;
2436 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2437 door_state &= ~DOOR_OPEN_2;
2438 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2439 door_state &= ~DOOR_CLOSE_2;
2441 door_delay_value = (door_state & DOOR_ACTION_1 ? door_1.step_delay :
2444 if (setup.quick_doors)
2446 stepsize = 20; /* must be choosen to always draw last frame */
2447 door_delay_value = 0;
2450 if (global.autoplay_leveldir)
2452 door_state |= DOOR_NO_DELAY;
2453 door_state &= ~DOOR_CLOSE_ALL;
2456 if (door_state & DOOR_ACTION)
2458 boolean door_1_done = !(door_state & DOOR_ACTION_1);
2459 boolean door_2_done = !(door_state & DOOR_ACTION_2);
2460 int start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2461 int end = (door_state & DOOR_ACTION_1 &&
2462 door_1.anim_mode == ANIM_VERTICAL ? DYSIZE : DXSIZE);
2465 if (!(door_state & DOOR_NO_DELAY) && !setup.quick_doors)
2467 /* opening door sound has priority over simultaneously closing door */
2468 if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
2469 PlaySoundStereo(SND_DOOR_OPENING, SOUND_MIDDLE);
2470 else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
2471 PlaySoundStereo(SND_DOOR_CLOSING, SOUND_MIDDLE);
2474 for (x = start; x <= end && !(door_1_done && door_2_done); x += stepsize)
2476 Bitmap *bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2477 GC gc = bitmap->stored_clip_gc;
2479 if (door_state & DOOR_ACTION_1)
2481 int a = MIN(x * door_1.step_offset, end);
2482 int i = (door_state & DOOR_OPEN_1 ? end - a : a);
2486 BlitBitmap(bitmap_db_door, drawto,
2487 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i / 2,
2488 DXSIZE, DYSIZE - i / 2, DX, DY);
2490 ClearRectangle(drawto, DX, DY + DYSIZE - i / 2, DXSIZE, i / 2);
2493 if (door_1.anim_mode == ANIM_HORIZONTAL && x <= DXSIZE)
2495 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
2496 int dst1_x = DX + DXSIZE - i, dst1_y = DY;
2497 int src2_x = DXSIZE - i, src2_y = DOOR_GFX_PAGEY1;
2498 int dst2_x = DX, dst2_y = DY;
2499 int width = i, height = DYSIZE;
2501 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2502 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2505 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2506 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2509 else if (door_1.anim_mode == ANIM_VERTICAL && x <= DYSIZE)
2511 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
2512 int dst1_x = DX, dst1_y = DY + DYSIZE - i;
2513 int src2_x = 0, src2_y = DOOR_GFX_PAGEY1 + DYSIZE - i;
2514 int dst2_x = DX, dst2_y = DY;
2515 int width = DXSIZE, height = i;
2517 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2518 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2521 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2522 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2525 else if (x <= DXSIZE) /* ANIM_DEFAULT */
2527 int j = (door_1.anim_mode == ANIM_DEFAULT ? (DXSIZE - i) / 3 : 0);
2529 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2530 BlitBitmapMasked(bitmap, drawto,
2531 DXSIZE, DOOR_GFX_PAGEY1, i, 77,
2532 DX + DXSIZE - i, DY + j);
2533 BlitBitmapMasked(bitmap, drawto,
2534 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
2535 DX + DXSIZE - i, DY + 140 + j);
2536 SetClipOrigin(bitmap, gc, DX - DXSIZE + i,
2537 DY - (DOOR_GFX_PAGEY1 + j));
2538 BlitBitmapMasked(bitmap, drawto,
2539 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
2541 BlitBitmapMasked(bitmap, drawto,
2542 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
2545 BlitBitmapMasked(bitmap, drawto,
2546 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2548 BlitBitmapMasked(bitmap, drawto,
2549 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2551 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2552 BlitBitmapMasked(bitmap, drawto,
2553 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2554 DX + DXSIZE - i, DY + 77 + j);
2555 BlitBitmapMasked(bitmap, drawto,
2556 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2557 DX + DXSIZE - i, DY + 203 + j);
2560 redraw_mask |= REDRAW_DOOR_1;
2561 door_1_done = (a == end);
2564 if (door_state & DOOR_ACTION_2)
2566 int a = MIN(x * door_2.step_offset, VXSIZE);
2567 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - a : a);
2571 BlitBitmap(bitmap_db_door, drawto,
2572 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i / 2,
2573 VXSIZE, VYSIZE - i / 2, VX, VY);
2575 ClearRectangle(drawto, VX, VY + VYSIZE - i / 2, VXSIZE, i / 2);
2578 if (door_2.anim_mode == ANIM_HORIZONTAL && x <= VXSIZE)
2580 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
2581 int dst1_x = VX + VXSIZE - i, dst1_y = VY;
2582 int src2_x = VXSIZE - i, src2_y = DOOR_GFX_PAGEY2;
2583 int dst2_x = VX, dst2_y = VY;
2584 int width = i, height = VYSIZE;
2586 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2587 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2590 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2591 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2594 else if (door_2.anim_mode == ANIM_VERTICAL && x <= VYSIZE)
2596 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
2597 int dst1_x = VX, dst1_y = VY + VYSIZE - i;
2598 int src2_x = 0, src2_y = DOOR_GFX_PAGEY2 + VYSIZE - i;
2599 int dst2_x = VX, dst2_y = VY;
2600 int width = VXSIZE, height = i;
2602 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2603 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2606 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2607 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2610 else if (x <= VXSIZE) /* ANIM_DEFAULT */
2612 int j = (door_2.anim_mode == ANIM_DEFAULT ? (VXSIZE - i) / 3 : 0);
2614 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2615 BlitBitmapMasked(bitmap, drawto,
2616 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
2617 VX + VXSIZE - i, VY + j);
2618 SetClipOrigin(bitmap, gc,
2619 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2620 BlitBitmapMasked(bitmap, drawto,
2621 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
2624 BlitBitmapMasked(bitmap, drawto,
2625 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2626 i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
2627 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2628 BlitBitmapMasked(bitmap, drawto,
2629 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2631 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2634 redraw_mask |= REDRAW_DOOR_2;
2635 door_2_done = (a == VXSIZE);
2640 if (game_status == GAME_MODE_MAIN)
2643 if (!(door_state & DOOR_NO_DELAY))
2644 WaitUntilDelayReached(&door_delay, door_delay_value);
2648 if (door_state & DOOR_ACTION_1)
2649 door1 = door_state & DOOR_ACTION_1;
2650 if (door_state & DOOR_ACTION_2)
2651 door2 = door_state & DOOR_ACTION_2;
2653 return (door1 | door2);
2656 void DrawSpecialEditorDoor()
2658 /* draw bigger toolbox window */
2659 BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
2660 DOOR_GFX_PAGEX7, 0, EXSIZE + 8, 8,
2662 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2663 EX - 4, VY - 4, EXSIZE + 8, EYSIZE - VYSIZE + 4,
2666 redraw_mask |= REDRAW_ALL;
2669 void UndrawSpecialEditorDoor()
2671 /* draw normal tape recorder window */
2672 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2673 EX - 4, EY - 12, EXSIZE + 8, EYSIZE - VYSIZE + 12,
2676 redraw_mask |= REDRAW_ALL;
2680 /* ---------- new tool button stuff ---------------------------------------- */
2682 /* graphic position values for tool buttons */
2683 #define TOOL_BUTTON_YES_XPOS 2
2684 #define TOOL_BUTTON_YES_YPOS 250
2685 #define TOOL_BUTTON_YES_GFX_YPOS 0
2686 #define TOOL_BUTTON_YES_XSIZE 46
2687 #define TOOL_BUTTON_YES_YSIZE 28
2688 #define TOOL_BUTTON_NO_XPOS 52
2689 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2690 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2691 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2692 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2693 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2694 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2695 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2696 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2697 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2698 #define TOOL_BUTTON_PLAYER_XSIZE 30
2699 #define TOOL_BUTTON_PLAYER_YSIZE 30
2700 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2701 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2702 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2703 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2704 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2705 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2706 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2707 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2708 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2709 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2710 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2711 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2712 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2713 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2714 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2715 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2716 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2717 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2718 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2719 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2728 } toolbutton_info[NUM_TOOL_BUTTONS] =
2731 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2732 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2733 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2738 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2739 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2740 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2745 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2746 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2747 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2748 TOOL_CTRL_ID_CONFIRM,
2752 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2753 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2754 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2755 TOOL_CTRL_ID_PLAYER_1,
2759 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2760 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2761 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2762 TOOL_CTRL_ID_PLAYER_2,
2766 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2767 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2768 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2769 TOOL_CTRL_ID_PLAYER_3,
2773 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2774 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2775 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2776 TOOL_CTRL_ID_PLAYER_4,
2781 void CreateToolButtons()
2785 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2787 Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2788 Bitmap *deco_bitmap = None;
2789 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2790 struct GadgetInfo *gi;
2791 unsigned long event_mask;
2792 int gd_xoffset, gd_yoffset;
2793 int gd_x1, gd_x2, gd_y;
2796 event_mask = GD_EVENT_RELEASED;
2798 gd_xoffset = toolbutton_info[i].xpos;
2799 gd_yoffset = toolbutton_info[i].ypos;
2800 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2801 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2802 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2804 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2806 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
2808 getMiniGraphicSource(PLAYER_NR_GFX(IMG_PLAYER_1, player_nr),
2809 &deco_bitmap, &deco_x, &deco_y);
2810 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2811 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2814 gi = CreateGadget(GDI_CUSTOM_ID, id,
2815 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2816 GDI_X, DX + toolbutton_info[i].x,
2817 GDI_Y, DY + toolbutton_info[i].y,
2818 GDI_WIDTH, toolbutton_info[i].width,
2819 GDI_HEIGHT, toolbutton_info[i].height,
2820 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2821 GDI_STATE, GD_BUTTON_UNPRESSED,
2822 GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
2823 GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
2824 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
2825 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2826 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2827 GDI_DECORATION_SHIFTING, 1, 1,
2828 GDI_EVENT_MASK, event_mask,
2829 GDI_CALLBACK_ACTION, HandleToolButtons,
2833 Error(ERR_EXIT, "cannot create gadget");
2835 tool_gadget[id] = gi;
2839 void FreeToolButtons()
2843 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2844 FreeGadget(tool_gadget[i]);
2847 static void UnmapToolButtons()
2851 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2852 UnmapGadget(tool_gadget[i]);
2855 static void HandleToolButtons(struct GadgetInfo *gi)
2857 request_gadget_id = gi->custom_id;
2860 static struct Mapping_EM_to_RND_object
2863 boolean is_rnd_to_em_mapping; /* unique mapping EM <-> RND */
2864 boolean is_backside; /* backside of moving element */
2870 em_object_mapping_list[] =
2873 Xblank, TRUE, FALSE,
2877 Yacid_splash_eB, FALSE, FALSE,
2878 EL_ACID_SPLASH_RIGHT, -1, -1
2881 Yacid_splash_wB, FALSE, FALSE,
2882 EL_ACID_SPLASH_LEFT, -1, -1
2885 #ifdef EM_ENGINE_BAD_ROLL
2887 Xstone_force_e, FALSE, FALSE,
2888 EL_ROCK, -1, MV_BIT_RIGHT
2891 Xstone_force_w, FALSE, FALSE,
2892 EL_ROCK, -1, MV_BIT_LEFT
2895 Xnut_force_e, FALSE, FALSE,
2896 EL_NUT, -1, MV_BIT_RIGHT
2899 Xnut_force_w, FALSE, FALSE,
2900 EL_NUT, -1, MV_BIT_LEFT
2903 Xspring_force_e, FALSE, FALSE,
2904 EL_SPRING, -1, MV_BIT_RIGHT
2907 Xspring_force_w, FALSE, FALSE,
2908 EL_SPRING, -1, MV_BIT_LEFT
2911 Xemerald_force_e, FALSE, FALSE,
2912 EL_EMERALD, -1, MV_BIT_RIGHT
2915 Xemerald_force_w, FALSE, FALSE,
2916 EL_EMERALD, -1, MV_BIT_LEFT
2919 Xdiamond_force_e, FALSE, FALSE,
2920 EL_DIAMOND, -1, MV_BIT_RIGHT
2923 Xdiamond_force_w, FALSE, FALSE,
2924 EL_DIAMOND, -1, MV_BIT_LEFT
2927 Xbomb_force_e, FALSE, FALSE,
2928 EL_BOMB, -1, MV_BIT_RIGHT
2931 Xbomb_force_w, FALSE, FALSE,
2932 EL_BOMB, -1, MV_BIT_LEFT
2934 #endif /* EM_ENGINE_BAD_ROLL */
2937 Xstone, TRUE, FALSE,
2941 Xstone_pause, FALSE, FALSE,
2945 Xstone_fall, FALSE, FALSE,
2949 Ystone_s, FALSE, FALSE,
2950 EL_ROCK, ACTION_FALLING, -1
2953 Ystone_sB, FALSE, TRUE,
2954 EL_ROCK, ACTION_FALLING, -1
2957 Ystone_e, FALSE, FALSE,
2958 EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT
2961 Ystone_eB, FALSE, TRUE,
2962 EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT
2965 Ystone_w, FALSE, FALSE,
2966 EL_ROCK, ACTION_MOVING, MV_BIT_LEFT
2969 Ystone_wB, FALSE, TRUE,
2970 EL_ROCK, ACTION_MOVING, MV_BIT_LEFT
2977 Xnut_pause, FALSE, FALSE,
2981 Xnut_fall, FALSE, FALSE,
2985 Ynut_s, FALSE, FALSE,
2986 EL_NUT, ACTION_FALLING, -1
2989 Ynut_sB, FALSE, TRUE,
2990 EL_NUT, ACTION_FALLING, -1
2993 Ynut_e, FALSE, FALSE,
2994 EL_NUT, ACTION_MOVING, MV_BIT_RIGHT
2997 Ynut_eB, FALSE, TRUE,
2998 EL_NUT, ACTION_MOVING, MV_BIT_RIGHT
3001 Ynut_w, FALSE, FALSE,
3002 EL_NUT, ACTION_MOVING, MV_BIT_LEFT
3005 Ynut_wB, FALSE, TRUE,
3006 EL_NUT, ACTION_MOVING, MV_BIT_LEFT
3009 Xbug_n, TRUE, FALSE,
3013 Xbug_e, TRUE, FALSE,
3014 EL_BUG_RIGHT, -1, -1
3017 Xbug_s, TRUE, FALSE,
3021 Xbug_w, TRUE, FALSE,
3025 Xbug_gon, FALSE, FALSE,
3029 Xbug_goe, FALSE, FALSE,
3030 EL_BUG_RIGHT, -1, -1
3033 Xbug_gos, FALSE, FALSE,
3037 Xbug_gow, FALSE, FALSE,
3041 Ybug_n, FALSE, FALSE,
3042 EL_BUG, ACTION_MOVING, MV_BIT_UP
3045 Ybug_nB, FALSE, TRUE,
3046 EL_BUG, ACTION_MOVING, MV_BIT_UP
3049 Ybug_e, FALSE, FALSE,
3050 EL_BUG, ACTION_MOVING, MV_BIT_RIGHT
3053 Ybug_eB, FALSE, TRUE,
3054 EL_BUG, ACTION_MOVING, MV_BIT_RIGHT
3057 Ybug_s, FALSE, FALSE,
3058 EL_BUG, ACTION_MOVING, MV_BIT_DOWN
3061 Ybug_sB, FALSE, TRUE,
3062 EL_BUG, ACTION_MOVING, MV_BIT_DOWN
3065 Ybug_w, FALSE, FALSE,
3066 EL_BUG, ACTION_MOVING, MV_BIT_LEFT
3069 Ybug_wB, FALSE, TRUE,
3070 EL_BUG, ACTION_MOVING, MV_BIT_LEFT
3073 Ybug_w_n, FALSE, FALSE,
3074 EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_UP
3077 Ybug_n_e, FALSE, FALSE,
3078 EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3081 Ybug_e_s, FALSE, FALSE,
3082 EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
3085 Ybug_s_w, FALSE, FALSE,
3086 EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3089 Ybug_e_n, FALSE, FALSE,
3090 EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
3093 Ybug_s_e, FALSE, FALSE,
3094 EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3097 Ybug_w_s, FALSE, FALSE,
3098 EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
3101 Ybug_n_w, FALSE, FALSE,
3102 EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3105 Ybug_stone, FALSE, FALSE,
3106 EL_BUG, ACTION_SMASHED_BY_ROCK, -1
3109 Ybug_spring, FALSE, FALSE,
3110 EL_BUG, ACTION_SMASHED_BY_SPRING, -1
3113 Xtank_n, TRUE, FALSE,
3114 EL_SPACESHIP_UP, -1, -1
3117 Xtank_e, TRUE, FALSE,
3118 EL_SPACESHIP_RIGHT, -1, -1
3121 Xtank_s, TRUE, FALSE,
3122 EL_SPACESHIP_DOWN, -1, -1
3125 Xtank_w, TRUE, FALSE,
3126 EL_SPACESHIP_LEFT, -1, -1
3129 Xtank_gon, FALSE, FALSE,
3130 EL_SPACESHIP_UP, -1, -1
3133 Xtank_goe, FALSE, FALSE,
3134 EL_SPACESHIP_RIGHT, -1, -1
3137 Xtank_gos, FALSE, FALSE,
3138 EL_SPACESHIP_DOWN, -1, -1
3141 Xtank_gow, FALSE, FALSE,
3142 EL_SPACESHIP_LEFT, -1, -1
3145 Ytank_n, FALSE, FALSE,
3146 EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP
3149 Ytank_nB, FALSE, TRUE,
3150 EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP
3153 Ytank_e, FALSE, FALSE,
3154 EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT
3157 Ytank_eB, FALSE, TRUE,
3158 EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT
3161 Ytank_s, FALSE, FALSE,
3162 EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN
3165 Ytank_sB, FALSE, TRUE,
3166 EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN
3169 Ytank_w, FALSE, FALSE,
3170 EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT
3173 Ytank_wB, FALSE, TRUE,
3174 EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT
3177 Ytank_w_n, FALSE, FALSE,
3178 EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_UP
3181 Ytank_n_e, FALSE, FALSE,
3182 EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3185 Ytank_e_s, FALSE, FALSE,
3186 EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
3189 Ytank_s_w, FALSE, FALSE,
3190 EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3193 Ytank_e_n, FALSE, FALSE,
3194 EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
3197 Ytank_s_e, FALSE, FALSE,
3198 EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3201 Ytank_w_s, FALSE, FALSE,
3202 EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
3205 Ytank_n_w, FALSE, FALSE,
3206 EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3209 Ytank_stone, FALSE, FALSE,
3210 EL_SPACESHIP, ACTION_SMASHED_BY_ROCK, -1
3213 Ytank_spring, FALSE, FALSE,
3214 EL_SPACESHIP, ACTION_SMASHED_BY_SPRING, -1
3217 Xandroid, TRUE, FALSE,
3218 EL_EMC_ANDROID, ACTION_ACTIVE, -1
3221 Xandroid_1_n, FALSE, FALSE,
3222 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_UP
3225 Xandroid_2_n, FALSE, FALSE,
3226 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_UP
3229 Xandroid_1_e, FALSE, FALSE,
3230 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_RIGHT
3233 Xandroid_2_e, FALSE, FALSE,
3234 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_RIGHT
3237 Xandroid_1_w, FALSE, FALSE,
3238 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_LEFT
3241 Xandroid_2_w, FALSE, FALSE,
3242 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_LEFT
3245 Xandroid_1_s, FALSE, FALSE,
3246 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_DOWN
3249 Xandroid_2_s, FALSE, FALSE,
3250 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_DOWN
3253 Yandroid_n, FALSE, FALSE,
3254 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_UP
3257 Yandroid_nB, FALSE, TRUE,
3258 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_UP
3261 Yandroid_ne, FALSE, FALSE,
3262 EL_EMC_ANDROID, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3265 Yandroid_neB, FALSE, TRUE,
3266 EL_EMC_ANDROID, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3269 Yandroid_e, FALSE, FALSE,
3270 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_RIGHT
3273 Yandroid_eB, FALSE, TRUE,
3274 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_RIGHT
3277 Yandroid_se, FALSE, FALSE,
3278 EL_EMC_ANDROID, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3281 Yandroid_seB, FALSE, TRUE,
3282 EL_EMC_ANDROID, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3285 Yandroid_s, FALSE, FALSE,
3286 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_DOWN
3289 Yandroid_sB, FALSE, TRUE,
3290 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_DOWN
3293 Yandroid_sw, FALSE, FALSE,
3294 EL_EMC_ANDROID, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3297 Yandroid_swB, FALSE, TRUE,
3298 EL_EMC_ANDROID, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3301 Yandroid_w, FALSE, FALSE,
3302 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_LEFT
3305 Yandroid_wB, FALSE, TRUE,
3306 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_LEFT
3309 Yandroid_nw, FALSE, FALSE,
3310 EL_EMC_ANDROID, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3313 Yandroid_nwB, FALSE, TRUE,
3314 EL_EMC_ANDROID, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3317 Xspring, TRUE, FALSE,
3321 Xspring_pause, FALSE, FALSE,
3325 Xspring_e, FALSE, FALSE,
3329 Xspring_w, FALSE, FALSE,
3333 Xspring_fall, FALSE, FALSE,
3337 Yspring_s, FALSE, FALSE,
3338 EL_SPRING, ACTION_FALLING, -1
3341 Yspring_sB, FALSE, TRUE,
3342 EL_SPRING, ACTION_FALLING, -1
3345 Yspring_e, FALSE, FALSE,
3346 EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT
3349 Yspring_eB, FALSE, TRUE,
3350 EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT
3353 Yspring_w, FALSE, FALSE,
3354 EL_SPRING, ACTION_MOVING, MV_BIT_LEFT
3357 Yspring_wB, FALSE, TRUE,
3358 EL_SPRING, ACTION_MOVING, MV_BIT_LEFT
3361 Yspring_kill_e, FALSE, FALSE,
3362 EL_ROBOT, ACTION_SLURPED_BY_SPRING, MV_BIT_RIGHT
3365 Yspring_kill_eB, FALSE, TRUE,
3366 EL_ROBOT, ACTION_SLURPED_BY_SPRING, MV_BIT_RIGHT
3369 Yspring_kill_w, FALSE, FALSE,
3370 EL_ROBOT, ACTION_SLURPED_BY_SPRING, MV_BIT_LEFT
3373 Yspring_kill_wB, FALSE, TRUE,
3374 EL_ROBOT, ACTION_SLURPED_BY_SPRING, MV_BIT_LEFT
3377 Xeater_n, TRUE, FALSE,
3381 Xeater_e, FALSE, FALSE,
3385 Xeater_w, FALSE, FALSE,
3389 Xeater_s, FALSE, FALSE,
3393 Yeater_n, FALSE, FALSE,
3394 EL_YAMYAM, ACTION_MOVING, MV_BIT_UP
3397 Yeater_nB, FALSE, TRUE,
3398 EL_YAMYAM, ACTION_MOVING, MV_BIT_UP
3401 Yeater_e, FALSE, FALSE,
3402 EL_YAMYAM, ACTION_MOVING, MV_BIT_RIGHT
3405 Yeater_eB, FALSE, TRUE,
3406 EL_YAMYAM, ACTION_MOVING, MV_BIT_RIGHT
3409 Yeater_s, FALSE, FALSE,
3410 EL_YAMYAM, ACTION_MOVING, MV_BIT_DOWN
3413 Yeater_sB, FALSE, TRUE,
3414 EL_YAMYAM, ACTION_MOVING, MV_BIT_DOWN
3417 Yeater_w, FALSE, FALSE,
3418 EL_YAMYAM, ACTION_MOVING, MV_BIT_LEFT
3421 Yeater_wB, FALSE, TRUE,
3422 EL_YAMYAM, ACTION_MOVING, MV_BIT_LEFT
3425 Yeater_stone, FALSE, FALSE,
3426 EL_YAMYAM, ACTION_SMASHED_BY_ROCK, -1
3429 Yeater_spring, FALSE, FALSE,
3430 EL_YAMYAM, ACTION_SMASHED_BY_SPRING, -1
3433 Xalien, TRUE, FALSE,
3437 Xalien_pause, FALSE, FALSE,
3441 Yalien_n, FALSE, FALSE,
3442 EL_ROBOT, ACTION_MOVING, MV_BIT_UP
3445 Yalien_nB, FALSE, TRUE,
3446 EL_ROBOT, ACTION_MOVING, MV_BIT_UP
3449 Yalien_e, FALSE, FALSE,
3450 EL_ROBOT, ACTION_MOVING, MV_BIT_RIGHT
3453 Yalien_eB, FALSE, TRUE,
3454 EL_ROBOT, ACTION_MOVING, MV_BIT_RIGHT
3457 Yalien_s, FALSE, FALSE,
3458 EL_ROBOT, ACTION_MOVING, MV_BIT_DOWN
3461 Yalien_sB, FALSE, TRUE,
3462 EL_ROBOT, ACTION_MOVING, MV_BIT_DOWN
3465 Yalien_w, FALSE, FALSE,
3466 EL_ROBOT, ACTION_MOVING, MV_BIT_LEFT
3469 Yalien_wB, FALSE, TRUE,
3470 EL_ROBOT, ACTION_MOVING, MV_BIT_LEFT
3473 Yalien_stone, FALSE, FALSE,
3474 EL_ROBOT, ACTION_SMASHED_BY_ROCK, -1
3477 Yalien_spring, FALSE, FALSE,
3478 EL_ROBOT, ACTION_SMASHED_BY_SPRING, -1
3481 Xemerald, TRUE, FALSE,
3485 Xemerald_pause, FALSE, FALSE,
3489 Xemerald_fall, FALSE, FALSE,
3493 Xemerald_shine, FALSE, FALSE,
3494 EL_EMERALD, ACTION_TWINKLING, -1
3497 Yemerald_s, FALSE, FALSE,
3498 EL_EMERALD, ACTION_FALLING, -1
3501 Yemerald_sB, FALSE, TRUE,
3502 EL_EMERALD, ACTION_FALLING, -1
3505 Yemerald_e, FALSE, FALSE,
3506 EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT
3509 Yemerald_eB, FALSE, TRUE,
3510 EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT
3513 Yemerald_w, FALSE, FALSE,
3514 EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT
3517 Yemerald_wB, FALSE, TRUE,
3518 EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT
3521 Yemerald_eat, FALSE, FALSE,
3522 EL_EMERALD, ACTION_COLLECTING, -1
3525 Yemerald_stone, FALSE, FALSE,
3526 EL_NUT, ACTION_BREAKING, -1
3529 Xdiamond, TRUE, FALSE,
3533 Xdiamond_pause, FALSE, FALSE,
3537 Xdiamond_fall, FALSE, FALSE,
3541 Xdiamond_shine, FALSE, FALSE,
3542 EL_DIAMOND, ACTION_TWINKLING, -1
3545 Ydiamond_s, FALSE, FALSE,
3546 EL_DIAMOND, ACTION_FALLING, -1
3549 Ydiamond_sB, FALSE, TRUE,
3550 EL_DIAMOND, ACTION_FALLING, -1
3553 Ydiamond_e, FALSE, FALSE,
3554 EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT
3557 Ydiamond_eB, FALSE, TRUE,
3558 EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT
3561 Ydiamond_w, FALSE, FALSE,
3562 EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT
3565 Ydiamond_wB, FALSE, TRUE,
3566 EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT
3569 Ydiamond_eat, FALSE, FALSE,
3570 EL_DIAMOND, ACTION_COLLECTING, -1
3573 Ydiamond_stone, FALSE, FALSE,
3574 EL_DIAMOND, ACTION_SMASHED_BY_ROCK, -1
3577 Xdrip_fall, TRUE, FALSE,
3578 EL_AMOEBA_DROP, -1, -1
3581 Xdrip_stretch, FALSE, FALSE,
3582 EL_AMOEBA_DROP, ACTION_FALLING, -1
3585 Xdrip_stretchB, FALSE, TRUE,
3586 EL_AMOEBA_DROP, ACTION_FALLING, -1
3589 Xdrip_eat, FALSE, FALSE,
3590 EL_AMOEBA_DROP, ACTION_GROWING, -1
3593 Ydrip_s1, FALSE, FALSE,
3594 EL_AMOEBA_DROP, ACTION_FALLING, -1
3597 Ydrip_s1B, FALSE, TRUE,
3598 EL_AMOEBA_DROP, ACTION_FALLING, -1
3601 Ydrip_s2, FALSE, FALSE,
3602 EL_AMOEBA_DROP, ACTION_FALLING, -1
3605 Ydrip_s2B, FALSE, TRUE,
3606 EL_AMOEBA_DROP, ACTION_FALLING, -1
3613 Xbomb_pause, FALSE, FALSE,
3617 Xbomb_fall, FALSE, FALSE,
3621 Ybomb_s, FALSE, FALSE,
3622 EL_BOMB, ACTION_FALLING, -1
3625 Ybomb_sB, FALSE, TRUE,
3626 EL_BOMB, ACTION_FALLING, -1
3629 Ybomb_e, FALSE, FALSE,
3630 EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT
3633 Ybomb_eB, FALSE, TRUE,
3634 EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT
3637 Ybomb_w, FALSE, FALSE,
3638 EL_BOMB, ACTION_MOVING, MV_BIT_LEFT
3641 Ybomb_wB, FALSE, TRUE,
3642 EL_BOMB, ACTION_MOVING, MV_BIT_LEFT
3645 Ybomb_eat, FALSE, FALSE,
3646 EL_BOMB, ACTION_ACTIVATING, -1
3649 Xballoon, TRUE, FALSE,
3653 Yballoon_n, FALSE, FALSE,
3654 EL_BALLOON, ACTION_MOVING, MV_BIT_UP
3657 Yballoon_nB, FALSE, TRUE,
3658 EL_BALLOON, ACTION_MOVING, MV_BIT_UP
3661 Yballoon_e, FALSE, FALSE,
3662 EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT
3665 Yballoon_eB, FALSE, TRUE,
3666 EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT
3669 Yballoon_s, FALSE, FALSE,
3670 EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN
3673 Yballoon_sB, FALSE, TRUE,
3674 EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN
3677 Yballoon_w, FALSE, FALSE,
3678 EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT
3681 Yballoon_wB, FALSE, TRUE,
3682 EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT
3685 Xgrass, TRUE, FALSE,
3686 EL_EMC_GRASS, -1, -1
3689 Ygrass_nB, FALSE, FALSE,
3690 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_UP
3693 Ygrass_eB, FALSE, FALSE,
3694 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_RIGHT
3697 Ygrass_sB, FALSE, FALSE,
3698 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_DOWN
3701 Ygrass_wB, FALSE, FALSE,
3702 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_LEFT
3709 Ydirt_nB, FALSE, FALSE,
3710 EL_SAND, ACTION_DIGGING, MV_BIT_UP
3713 Ydirt_eB, FALSE, FALSE,
3714 EL_SAND, ACTION_DIGGING, MV_BIT_RIGHT
3717 Ydirt_sB, FALSE, FALSE,
3718 EL_SAND, ACTION_DIGGING, MV_BIT_DOWN
3721 Ydirt_wB, FALSE, FALSE,
3722 EL_SAND, ACTION_DIGGING, MV_BIT_LEFT
3725 Xacid_ne, TRUE, FALSE,
3726 EL_ACID_POOL_TOPRIGHT, -1, -1
3729 Xacid_se, TRUE, FALSE,
3730 EL_ACID_POOL_BOTTOMRIGHT, -1, -1
3733 Xacid_s, TRUE, FALSE,
3734 EL_ACID_POOL_BOTTOM, -1, -1
3737 Xacid_sw, TRUE, FALSE,
3738 EL_ACID_POOL_BOTTOMLEFT, -1, -1
3741 Xacid_nw, TRUE, FALSE,
3742 EL_ACID_POOL_TOPLEFT, -1, -1
3745 Xacid_1, TRUE, FALSE,
3749 Xacid_2, FALSE, FALSE,
3753 Xacid_3, FALSE, FALSE,
3757 Xacid_4, FALSE, FALSE,
3761 Xacid_5, FALSE, FALSE,
3765 Xacid_6, FALSE, FALSE,
3769 Xacid_7, FALSE, FALSE,
3773 Xacid_8, FALSE, FALSE,
3777 Xball_1, TRUE, FALSE,
3778 EL_EMC_MAGIC_BALL, -1, -1
3781 Xball_1B, FALSE, FALSE,
3782 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
3785 Xball_2, FALSE, FALSE,
3786 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
3789 Xball_2B, FALSE, FALSE,
3790 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
3793 Yball_eat, FALSE, FALSE,
3794 EL_EMC_MAGIC_BALL, ACTION_DROPPING, -1
3797 Ykey_1_eat, FALSE, FALSE,
3798 EL_EM_KEY_1, ACTION_COLLECTING, -1
3801 Ykey_2_eat, FALSE, FALSE,
3802 EL_EM_KEY_2, ACTION_COLLECTING, -1
3805 Ykey_3_eat, FALSE, FALSE,
3806 EL_EM_KEY_3, ACTION_COLLECTING, -1
3809 Ykey_4_eat, FALSE, FALSE,
3810 EL_EM_KEY_4, ACTION_COLLECTING, -1
3813 Ykey_5_eat, FALSE, FALSE,
3814 EL_EMC_KEY_5, ACTION_COLLECTING, -1
3817 Ykey_6_eat, FALSE, FALSE,
3818 EL_EMC_KEY_6, ACTION_COLLECTING, -1
3821 Ykey_7_eat, FALSE, FALSE,
3822 EL_EMC_KEY_7, ACTION_COLLECTING, -1
3825 Ykey_8_eat, FALSE, FALSE,
3826 EL_EMC_KEY_8, ACTION_COLLECTING, -1
3829 Ylenses_eat, FALSE, FALSE,
3830 EL_EMC_LENSES, ACTION_COLLECTING, -1
3833 Ymagnify_eat, FALSE, FALSE,
3834 EL_EMC_MAGNIFIER, ACTION_COLLECTING, -1
3837 Ygrass_eat, FALSE, FALSE,
3838 EL_EMC_GRASS, ACTION_SNAPPING, -1
3841 Ydirt_eat, FALSE, FALSE,
3842 EL_SAND, ACTION_SNAPPING, -1
3845 Xgrow_ns, TRUE, FALSE,
3846 EL_EXPANDABLE_WALL_VERTICAL, -1, -1
3849 Ygrow_ns_eat, FALSE, FALSE,
3850 EL_EXPANDABLE_WALL_VERTICAL, ACTION_GROWING, -1
3853 Xgrow_ew, TRUE, FALSE,
3854 EL_EXPANDABLE_WALL_HORIZONTAL, -1, -1
3857 Ygrow_ew_eat, FALSE, FALSE,
3858 EL_EXPANDABLE_WALL_HORIZONTAL, ACTION_GROWING, -1
3861 Xwonderwall, TRUE, FALSE,
3862 EL_MAGIC_WALL, -1, -1
3865 XwonderwallB, FALSE, FALSE,
3866 EL_MAGIC_WALL, ACTION_ACTIVE, -1
3869 Xamoeba_1, TRUE, FALSE,
3870 EL_AMOEBA_DRY, ACTION_OTHER, -1
3873 Xamoeba_2, FALSE, FALSE,
3874 EL_AMOEBA_DRY, ACTION_OTHER, -1
3877 Xamoeba_3, FALSE, FALSE,
3878 EL_AMOEBA_DRY, ACTION_OTHER, -1
3881 Xamoeba_4, FALSE, FALSE,
3882 EL_AMOEBA_DRY, ACTION_OTHER, -1
3885 Xamoeba_5, TRUE, FALSE,
3886 EL_AMOEBA_WET, ACTION_OTHER, -1
3889 Xamoeba_6, FALSE, FALSE,
3890 EL_AMOEBA_WET, ACTION_OTHER, -1
3893 Xamoeba_7, FALSE, FALSE,
3894 EL_AMOEBA_WET, ACTION_OTHER, -1
3897 Xamoeba_8, FALSE, FALSE,
3898 EL_AMOEBA_WET, ACTION_OTHER, -1
3901 Xdoor_1, TRUE, FALSE,
3902 EL_EM_GATE_1, -1, -1
3905 Xdoor_2, TRUE, FALSE,
3906 EL_EM_GATE_2, -1, -1
3909 Xdoor_3, TRUE, FALSE,
3910 EL_EM_GATE_3, -1, -1
3913 Xdoor_4, TRUE, FALSE,
3914 EL_EM_GATE_4, -1, -1
3917 Xdoor_5, TRUE, FALSE,
3918 EL_EMC_GATE_5, -1, -1
3921 Xdoor_6, TRUE, FALSE,
3922 EL_EMC_GATE_6, -1, -1
3925 Xdoor_7, TRUE, FALSE,
3926 EL_EMC_GATE_7, -1, -1
3929 Xdoor_8, TRUE, FALSE,
3930 EL_EMC_GATE_8, -1, -1
3933 Xkey_1, TRUE, FALSE,
3937 Xkey_2, TRUE, FALSE,
3941 Xkey_3, TRUE, FALSE,
3945 Xkey_4, TRUE, FALSE,
3949 Xkey_5, TRUE, FALSE,
3950 EL_EMC_KEY_5, -1, -1
3953 Xkey_6, TRUE, FALSE,
3954 EL_EMC_KEY_6, -1, -1
3957 Xkey_7, TRUE, FALSE,
3958 EL_EMC_KEY_7, -1, -1
3961 Xkey_8, TRUE, FALSE,
3962 EL_EMC_KEY_8, -1, -1
3965 Xwind_n, TRUE, FALSE,
3966 EL_BALLOON_SWITCH_UP, -1, -1
3969 Xwind_e, TRUE, FALSE,
3970 EL_BALLOON_SWITCH_RIGHT, -1, -1
3973 Xwind_s, TRUE, FALSE,
3974 EL_BALLOON_SWITCH_DOWN, -1, -1
3977 Xwind_w, TRUE, FALSE,
3978 EL_BALLOON_SWITCH_LEFT, -1, -1
3981 Xwind_nesw, TRUE, FALSE,
3982 EL_BALLOON_SWITCH_ANY, -1, -1
3985 Xwind_stop, TRUE, FALSE,
3986 EL_BALLOON_SWITCH_NONE, -1, -1
3990 EL_EXIT_CLOSED, -1, -1
3993 Xexit_1, TRUE, FALSE,
3994 EL_EXIT_OPEN, -1, -1
3997 Xexit_2, FALSE, FALSE,
3998 EL_EXIT_OPEN, -1, -1
4001 Xexit_3, FALSE, FALSE,
4002 EL_EXIT_OPEN, -1, -1
4005 Xdynamite, TRUE, FALSE,
4009 Ydynamite_eat, FALSE, FALSE,
4010 EL_DYNAMITE, ACTION_COLLECTING, -1
4013 Xdynamite_1, TRUE, FALSE,
4014 EL_DYNAMITE_ACTIVE, -1, -1
4017 Xdynamite_2, FALSE, FALSE,
4018 EL_DYNAMITE_ACTIVE, -1, -1
4021 Xdynamite_3, FALSE, FALSE,
4022 EL_DYNAMITE_ACTIVE, -1, -1
4025 Xdynamite_4, FALSE, FALSE,
4026 EL_DYNAMITE_ACTIVE, -1, -1
4029 Xbumper, TRUE, FALSE,
4030 EL_EMC_SPRING_BUMPER, -1, -1
4033 XbumperB, FALSE, FALSE,
4034 EL_EMC_SPRING_BUMPER, ACTION_ACTIVE, -1
4037 Xwheel, TRUE, FALSE,
4038 EL_ROBOT_WHEEL, -1, -1
4041 XwheelB, FALSE, FALSE,
4042 EL_ROBOT_WHEEL, ACTION_ACTIVE, -1
4045 Xswitch, TRUE, FALSE,
4046 EL_EMC_MAGIC_BALL_SWITCH, -1, -1
4049 XswitchB, FALSE, FALSE,
4050 EL_EMC_MAGIC_BALL_SWITCH, ACTION_ACTIVE, -1
4054 EL_QUICKSAND_EMPTY, -1, -1
4057 Xsand_stone, TRUE, FALSE,
4058 EL_QUICKSAND_FULL, -1, -1
4061 Xsand_stonein_1, FALSE, FALSE,
4062 EL_ROCK, ACTION_FILLING, -1
4065 Xsand_stonein_2, FALSE, FALSE,
4066 EL_ROCK, ACTION_FILLING, -1
4069 Xsand_stonein_3, FALSE, FALSE,
4070 EL_ROCK, ACTION_FILLING, -1
4073 Xsand_stonein_4, FALSE, FALSE,
4074 EL_ROCK, ACTION_FILLING, -1
4077 Xsand_stonesand_1, FALSE, FALSE,
4078 EL_QUICKSAND_FULL, -1, -1
4081 Xsand_stonesand_2, FALSE, FALSE,
4082 EL_QUICKSAND_FULL, -1, -1
4085 Xsand_stonesand_3, FALSE, FALSE,
4086 EL_QUICKSAND_FULL, -1, -1
4089 Xsand_stonesand_4, FALSE, FALSE,
4090 EL_QUICKSAND_FULL, -1, -1
4093 Xsand_stoneout_1, FALSE, FALSE,
4094 EL_ROCK, ACTION_EMPTYING, -1
4097 Xsand_stoneout_2, FALSE, FALSE,
4098 EL_ROCK, ACTION_EMPTYING, -1
4101 Xsand_sandstone_1, FALSE, FALSE,
4102 EL_QUICKSAND_FULL, -1, -1
4105 Xsand_sandstone_2, FALSE, FALSE,
4106 EL_QUICKSAND_FULL, -1, -1
4109 Xsand_sandstone_3, FALSE, FALSE,
4110 EL_QUICKSAND_FULL, -1, -1
4113 Xsand_sandstone_4, FALSE, FALSE,
4114 EL_QUICKSAND_FULL, -1, -1
4117 Xplant, TRUE, FALSE,
4118 EL_EMC_PLANT, -1, -1
4121 Yplant, FALSE, FALSE,
4122 EL_EMC_PLANT, -1, -1
4125 Xlenses, TRUE, FALSE,
4126 EL_EMC_LENSES, -1, -1
4129 Xmagnify, TRUE, FALSE,
4130 EL_EMC_MAGNIFIER, -1, -1
4133 Xdripper, TRUE, FALSE,
4134 EL_EMC_DRIPPER, -1, -1
4137 XdripperB, FALSE, FALSE,
4138 EL_EMC_DRIPPER, ACTION_ACTIVE, -1
4141 Xfake_blank, TRUE, FALSE,
4142 EL_INVISIBLE_WALL, -1, -1
4145 Xfake_blankB, FALSE, FALSE,
4146 EL_INVISIBLE_WALL, ACTION_ACTIVE, -1
4149 Xfake_grass, TRUE, FALSE,
4150 EL_EMC_FAKE_GRASS, -1, -1
4153 Xfake_grassB, FALSE, FALSE,
4154 EL_EMC_FAKE_GRASS, ACTION_ACTIVE, -1
4157 Xfake_door_1, TRUE, FALSE,
4158 EL_EM_GATE_1_GRAY, -1, -1
4161 Xfake_door_2, TRUE, FALSE,
4162 EL_EM_GATE_2_GRAY, -1, -1
4165 Xfake_door_3, TRUE, FALSE,
4166 EL_EM_GATE_3_GRAY, -1, -1
4169 Xfake_door_4, TRUE, FALSE,
4170 EL_EM_GATE_4_GRAY, -1, -1
4173 Xfake_door_5, TRUE, FALSE,
4174 EL_EMC_GATE_5_GRAY, -1, -1
4177 Xfake_door_6, TRUE, FALSE,
4178 EL_EMC_GATE_6_GRAY, -1, -1
4181 Xfake_door_7, TRUE, FALSE,
4182 EL_EMC_GATE_7_GRAY, -1, -1
4185 Xfake_door_8, TRUE, FALSE,
4186 EL_EMC_GATE_8_GRAY, -1, -1
4189 Xfake_acid_1, TRUE, FALSE,
4190 EL_EMC_FAKE_ACID, -1, -1
4193 Xfake_acid_2, FALSE, FALSE,
4194 EL_EMC_FAKE_ACID, -1, -1
4197 Xfake_acid_3, FALSE, FALSE,
4198 EL_EMC_FAKE_ACID, -1, -1
4201 Xfake_acid_4, FALSE, FALSE,
4202 EL_EMC_FAKE_ACID, -1, -1
4205 Xfake_acid_5, FALSE, FALSE,
4206 EL_EMC_FAKE_ACID, -1, -1
4209 Xfake_acid_6, FALSE, FALSE,
4210 EL_EMC_FAKE_ACID, -1, -1
4213 Xfake_acid_7, FALSE, FALSE,
4214 EL_EMC_FAKE_ACID, -1, -1
4217 Xfake_acid_8, FALSE, FALSE,
4218 EL_EMC_FAKE_ACID, -1, -1
4221 Xsteel_1, TRUE, FALSE,
4222 EL_STEELWALL, -1, -1
4225 Xsteel_2, TRUE, FALSE,
4226 EL_EMC_STEELWALL_2, -1, -1
4229 Xsteel_3, TRUE, FALSE,
4230 EL_EMC_STEELWALL_3, -1, -1
4233 Xsteel_4, TRUE, FALSE,
4234 EL_EMC_STEELWALL_4, -1, -1
4237 Xwall_1, TRUE, FALSE,
4241 Xwall_2, TRUE, FALSE,
4242 EL_EMC_WALL_14, -1, -1
4245 Xwall_3, TRUE, FALSE,
4246 EL_EMC_WALL_15, -1, -1
4249 Xwall_4, TRUE, FALSE,
4250 EL_EMC_WALL_16, -1, -1
4253 Xround_wall_1, TRUE, FALSE,
4254 EL_WALL_SLIPPERY, -1, -1
4257 Xround_wall_2, TRUE, FALSE,
4258 EL_EMC_WALL_SLIPPERY_2, -1, -1
4261 Xround_wall_3, TRUE, FALSE,
4262 EL_EMC_WALL_SLIPPERY_3, -1, -1
4265 Xround_wall_4, TRUE, FALSE,
4266 EL_EMC_WALL_SLIPPERY_4, -1, -1
4269 Xdecor_1, TRUE, FALSE,
4270 EL_EMC_WALL_8, -1, -1
4273 Xdecor_2, TRUE, FALSE,
4274 EL_EMC_WALL_6, -1, -1
4277 Xdecor_3, TRUE, FALSE,
4278 EL_EMC_WALL_4, -1, -1
4281 Xdecor_4, TRUE, FALSE,
4282 EL_EMC_WALL_7, -1, -1
4285 Xdecor_5, TRUE, FALSE,
4286 EL_EMC_WALL_5, -1, -1
4289 Xdecor_6, TRUE, FALSE,
4290 EL_EMC_WALL_9, -1, -1
4293 Xdecor_7, TRUE, FALSE,
4294 EL_EMC_WALL_10, -1, -1
4297 Xdecor_8, TRUE, FALSE,
4298 EL_EMC_WALL_1, -1, -1
4301 Xdecor_9, TRUE, FALSE,
4302 EL_EMC_WALL_2, -1, -1
4305 Xdecor_10, TRUE, FALSE,
4306 EL_EMC_WALL_3, -1, -1
4309 Xdecor_11, TRUE, FALSE,
4310 EL_EMC_WALL_11, -1, -1
4313 Xdecor_12, TRUE, FALSE,
4314 EL_EMC_WALL_12, -1, -1
4317 Xalpha_0, TRUE, FALSE,
4318 EL_CHAR('0'), -1, -1
4321 Xalpha_1, TRUE, FALSE,
4322 EL_CHAR('1'), -1, -1
4325 Xalpha_2, TRUE, FALSE,
4326 EL_CHAR('2'), -1, -1
4329 Xalpha_3, TRUE, FALSE,
4330 EL_CHAR('3'), -1, -1
4333 Xalpha_4, TRUE, FALSE,
4334 EL_CHAR('4'), -1, -1
4337 Xalpha_5, TRUE, FALSE,
4338 EL_CHAR('5'), -1, -1
4341 Xalpha_6, TRUE, FALSE,
4342 EL_CHAR('6'), -1, -1
4345 Xalpha_7, TRUE, FALSE,
4346 EL_CHAR('7'), -1, -1
4349 Xalpha_8, TRUE, FALSE,
4350 EL_CHAR('8'), -1, -1
4353 Xalpha_9, TRUE, FALSE,
4354 EL_CHAR('9'), -1, -1
4357 Xalpha_excla, TRUE, FALSE,
4358 EL_CHAR('!'), -1, -1
4361 Xalpha_quote, TRUE, FALSE,
4362 EL_CHAR('"'), -1, -1
4365 Xalpha_comma, TRUE, FALSE,
4366 EL_CHAR(','), -1, -1
4369 Xalpha_minus, TRUE, FALSE,
4370 EL_CHAR('-'), -1, -1
4373 Xalpha_perio, TRUE, FALSE,
4374 EL_CHAR('.'), -1, -1
4377 Xalpha_colon, TRUE, FALSE,
4378 EL_CHAR(':'), -1, -1
4381 Xalpha_quest, TRUE, FALSE,
4382 EL_CHAR('?'), -1, -1
4385 Xalpha_a, TRUE, FALSE,
4386 EL_CHAR('A'), -1, -1
4389 Xalpha_b, TRUE, FALSE,
4390 EL_CHAR('B'), -1, -1
4393 Xalpha_c, TRUE, FALSE,
4394 EL_CHAR('C'), -1, -1
4397 Xalpha_d, TRUE, FALSE,
4398 EL_CHAR('D'), -1, -1
4401 Xalpha_e, TRUE, FALSE,
4402 EL_CHAR('E'), -1, -1
4405 Xalpha_f, TRUE, FALSE,
4406 EL_CHAR('F'), -1, -1
4409 Xalpha_g, TRUE, FALSE,
4410 EL_CHAR('G'), -1, -1
4413 Xalpha_h, TRUE, FALSE,
4414 EL_CHAR('H'), -1, -1
4417 Xalpha_i, TRUE, FALSE,
4418 EL_CHAR('I'), -1, -1
4421 Xalpha_j, TRUE, FALSE,
4422 EL_CHAR('J'), -1, -1
4425 Xalpha_k, TRUE, FALSE,
4426 EL_CHAR('K'), -1, -1
4429 Xalpha_l, TRUE, FALSE,
4430 EL_CHAR('L'), -1, -1
4433 Xalpha_m, TRUE, FALSE,
4434 EL_CHAR('M'), -1, -1
4437 Xalpha_n, TRUE, FALSE,
4438 EL_CHAR('N'), -1, -1
4441 Xalpha_o, TRUE, FALSE,
4442 EL_CHAR('O'), -1, -1
4445 Xalpha_p, TRUE, FALSE,
4446 EL_CHAR('P'), -1, -1
4449 Xalpha_q, TRUE, FALSE,
4450 EL_CHAR('Q'), -1, -1
4453 Xalpha_r, TRUE, FALSE,
4454 EL_CHAR('R'), -1, -1
4457 Xalpha_s, TRUE, FALSE,
4458 EL_CHAR('S'), -1, -1
4461 Xalpha_t, TRUE, FALSE,
4462 EL_CHAR('T'), -1, -1
4465 Xalpha_u, TRUE, FALSE,
4466 EL_CHAR('U'), -1, -1
4469 Xalpha_v, TRUE, FALSE,
4470 EL_CHAR('V'), -1, -1
4473 Xalpha_w, TRUE, FALSE,
4474 EL_CHAR('W'), -1, -1
4477 Xalpha_x, TRUE, FALSE,
4478 EL_CHAR('X'), -1, -1
4481 Xalpha_y, TRUE, FALSE,
4482 EL_CHAR('Y'), -1, -1
4485 Xalpha_z, TRUE, FALSE,
4486 EL_CHAR('Z'), -1, -1
4489 Xalpha_arrow_e, TRUE, FALSE,
4490 EL_CHAR('>'), -1, -1
4493 Xalpha_arrow_w, TRUE, FALSE,
4494 EL_CHAR('<'), -1, -1
4497 Xalpha_copyr, TRUE, FALSE,
4498 EL_CHAR('©'), -1, -1
4501 Xalpha_copyr, TRUE, FALSE,
4502 EL_CHAR('©'), -1, -1
4506 Xboom_bug, FALSE, FALSE,
4507 EL_BUG, ACTION_EXPLODING, -1
4510 Xboom_bomb, FALSE, FALSE,
4511 EL_BOMB, ACTION_EXPLODING, -1
4514 Xboom_android, FALSE, FALSE,
4515 EL_EMC_ANDROID, ACTION_OTHER, -1
4518 Xboom_1, FALSE, FALSE,
4519 EL_DEFAULT, ACTION_EXPLODING, -1
4522 Xboom_2, FALSE, FALSE,
4523 EL_DEFAULT, ACTION_EXPLODING, -1
4526 Znormal, FALSE, FALSE,
4530 Zdynamite, FALSE, FALSE,
4534 Zplayer, FALSE, FALSE,
4538 ZBORDER, FALSE, FALSE,
4548 static struct Mapping_EM_to_RND_player
4557 em_player_mapping_list[] =
4561 EL_PLAYER_1, ACTION_MOVING, MV_BIT_UP,
4565 EL_PLAYER_1, ACTION_MOVING, MV_BIT_RIGHT,
4569 EL_PLAYER_1, ACTION_MOVING, MV_BIT_DOWN,
4573 EL_PLAYER_1, ACTION_MOVING, MV_BIT_LEFT,
4577 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_UP,
4581 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_RIGHT,
4585 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_DOWN,
4589 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_LEFT,
4593 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_UP,
4597 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_RIGHT,
4601 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_DOWN,
4605 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_LEFT,
4609 EL_PLAYER_2, ACTION_MOVING, MV_BIT_UP,
4613 EL_PLAYER_2, ACTION_MOVING, MV_BIT_RIGHT,
4617 EL_PLAYER_2, ACTION_MOVING, MV_BIT_DOWN,
4621 EL_PLAYER_2, ACTION_MOVING, MV_BIT_LEFT,
4625 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_UP,
4629 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_RIGHT,
4633 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_DOWN,
4637 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_LEFT,
4641 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_UP,
4645 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_RIGHT,
4649 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_DOWN,
4653 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_LEFT,
4657 EL_PLAYER_1, ACTION_DEFAULT, -1,
4661 EL_PLAYER_2, ACTION_DEFAULT, -1,
4670 int map_element_RND_to_EM(int element_rnd)
4672 static unsigned short mapping_RND_to_EM[NUM_FILE_ELEMENTS];
4673 static boolean mapping_initialized = FALSE;
4675 if (!mapping_initialized)
4679 /* return "Xalpha_quest" for all undefined elements in mapping array */
4680 for (i = 0; i < NUM_FILE_ELEMENTS; i++)
4681 mapping_RND_to_EM[i] = Xalpha_quest;
4683 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
4684 if (em_object_mapping_list[i].is_rnd_to_em_mapping)
4685 mapping_RND_to_EM[em_object_mapping_list[i].element_rnd] =
4686 em_object_mapping_list[i].element_em;
4688 mapping_initialized = TRUE;
4691 if (element_rnd >= 0 && element_rnd < NUM_FILE_ELEMENTS)
4692 return mapping_RND_to_EM[element_rnd];
4694 Error(ERR_WARN, "invalid RND level element %d", element_rnd);
4699 int map_element_EM_to_RND(int element_em)
4701 static unsigned short mapping_EM_to_RND[TILE_MAX];
4702 static boolean mapping_initialized = FALSE;
4704 if (!mapping_initialized)
4708 /* return "EL_UNKNOWN" for all undefined elements in mapping array */
4709 for (i = 0; i < TILE_MAX; i++)
4710 mapping_EM_to_RND[i] = EL_UNKNOWN;
4712 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
4713 mapping_EM_to_RND[em_object_mapping_list[i].element_em] =
4714 em_object_mapping_list[i].element_rnd;
4716 mapping_initialized = TRUE;
4719 if (element_em >= 0 && element_em < TILE_MAX)
4720 return mapping_EM_to_RND[element_em];
4722 Error(ERR_WARN, "invalid EM level element %d", element_em);
4729 int map_element_RND_to_EM(int element_rnd)
4731 static unsigned short mapping_RND_to_EM[NUM_FILE_ELEMENTS];
4732 static boolean mapping_initialized = FALSE;
4739 mapping_RND_to_EM_list[] =
4741 { Xblank, EL_EMPTY },
4742 { Xstone, EL_ROCK },
4744 { Xbug_n, EL_BUG_UP },
4745 { Xbug_e, EL_BUG_RIGHT },
4746 { Xbug_s, EL_BUG_DOWN },
4747 { Xbug_w, EL_BUG_LEFT },
4748 { Xtank_n, EL_SPACESHIP_UP },
4749 { Xtank_e, EL_SPACESHIP_RIGHT },
4750 { Xtank_s, EL_SPACESHIP_DOWN },
4751 { Xtank_w, EL_SPACESHIP_LEFT },
4752 { Xandroid, EL_EMC_ANDROID },
4753 { Xandroid_1_n, EL_EMC_ANDROID_UP },
4754 { Xandroid_1_e, EL_EMC_ANDROID_RIGHT },
4755 { Xandroid_1_w, EL_EMC_ANDROID_LEFT },
4756 { Xandroid_1_s, EL_EMC_ANDROID_DOWN },
4757 { Xspring, EL_SPRING },
4758 { Xeater_n, EL_YAMYAM },
4759 { Xalien, EL_ROBOT },
4760 { Xemerald, EL_EMERALD },
4761 { Xdiamond, EL_DIAMOND },
4762 { Xdrip_fall, EL_AMOEBA_DROP },
4764 { Xballoon, EL_BALLOON },
4765 { Xgrass, EL_EMC_GRASS },
4767 { Xacid_ne, EL_ACID_POOL_TOPRIGHT },
4768 { Xacid_se, EL_ACID_POOL_BOTTOMRIGHT },
4769 { Xacid_s, EL_ACID_POOL_BOTTOM },
4770 { Xacid_sw, EL_ACID_POOL_BOTTOMLEFT },
4771 { Xacid_nw, EL_ACID_POOL_TOPLEFT },
4772 { Xacid_1, EL_ACID },
4773 { Xball_1, EL_EMC_MAGIC_BALL },
4774 { Xgrow_ns, EL_EMC_GROW },
4775 { Xwonderwall, EL_MAGIC_WALL },
4776 { Xamoeba_1, EL_AMOEBA_WET },
4777 { Xdoor_1, EL_EM_GATE_1 },
4778 { Xdoor_2, EL_EM_GATE_2 },
4779 { Xdoor_3, EL_EM_GATE_3 },
4780 { Xdoor_4, EL_EM_GATE_4 },
4781 { Xdoor_5, EL_EMC_GATE_5 },
4782 { Xdoor_6, EL_EMC_GATE_6 },
4783 { Xdoor_7, EL_EMC_GATE_7 },
4784 { Xdoor_8, EL_EMC_GATE_8 },
4785 { Xkey_1, EL_EM_KEY_1 },
4786 { Xkey_2, EL_EM_KEY_2 },
4787 { Xkey_3, EL_EM_KEY_3 },
4788 { Xkey_4, EL_EM_KEY_4 },
4789 { Xkey_5, EL_EMC_KEY_5 },
4790 { Xkey_6, EL_EMC_KEY_6 },
4791 { Xkey_7, EL_EMC_KEY_7 },
4792 { Xkey_8, EL_EMC_KEY_8 },
4793 { Xwind_n, EL_BALLOON_SWITCH_UP },
4794 { Xwind_e, EL_BALLOON_SWITCH_RIGHT },
4795 { Xwind_s, EL_BALLOON_SWITCH_DOWN },
4796 { Xwind_w, EL_BALLOON_SWITCH_LEFT },
4797 { Xwind_nesw, EL_BALLOON_SWITCH_ANY },
4798 { Xwind_stop, EL_BALLOON_SWITCH_NONE },
4799 { Xexit, EL_EXIT_CLOSED },
4800 { Xexit_1, EL_EXIT_OPEN },
4801 { Xdynamite, EL_DYNAMITE },
4802 { Xdynamite_1, EL_DYNAMITE_ACTIVE },
4803 { Xbumper, EL_EMC_BUMPER },
4804 { Xwheel, EL_ROBOT_WHEEL },
4805 { Xswitch, EL_UNKNOWN },
4806 { Xsand, EL_QUICKSAND_EMPTY },
4807 { Xsand_stone, EL_QUICKSAND_FULL },
4808 { Xplant, EL_EMC_PLANT },
4809 { Xlenses, EL_EMC_LENSES },
4810 { Xmagnify, EL_EMC_MAGNIFIER },
4811 { Xdripper, EL_UNKNOWN },
4812 { Xfake_blank, EL_INVISIBLE_WALL },
4813 { Xfake_grass, EL_INVISIBLE_SAND },
4814 { Xfake_door_1, EL_EM_GATE_1_GRAY },
4815 { Xfake_door_2, EL_EM_GATE_2_GRAY },
4816 { Xfake_door_3, EL_EM_GATE_3_GRAY },
4817 { Xfake_door_4, EL_EM_GATE_4_GRAY },
4818 { Xfake_door_5, EL_EMC_GATE_5_GRAY },
4819 { Xfake_door_6, EL_EMC_GATE_6_GRAY },
4820 { Xfake_door_7, EL_EMC_GATE_7_GRAY },
4821 { Xfake_door_8, EL_EMC_GATE_8_GRAY },
4822 { Xsteel_1, EL_STEELWALL },
4823 { Xsteel_2, EL_UNKNOWN },
4824 { Xsteel_3, EL_EMC_STEELWALL_1 },
4825 { Xsteel_4, EL_UNKNOWN },
4826 { Xwall_1, EL_WALL },
4827 { Xwall_2, EL_UNKNOWN },
4828 { Xwall_3, EL_UNKNOWN },
4829 { Xwall_4, EL_UNKNOWN },
4830 { Xround_wall_1, EL_WALL_SLIPPERY },
4831 { Xround_wall_2, EL_UNKNOWN },
4832 { Xround_wall_3, EL_UNKNOWN },
4833 { Xround_wall_4, EL_UNKNOWN },
4834 { Xdecor_1, EL_UNKNOWN },
4835 { Xdecor_2, EL_EMC_WALL_6 },
4836 { Xdecor_3, EL_EMC_WALL_4 },
4837 { Xdecor_4, EL_EMC_WALL_5 },
4838 { Xdecor_5, EL_EMC_WALL_7 },
4839 { Xdecor_6, EL_EMC_WALL_8 },
4840 { Xdecor_7, EL_UNKNOWN },
4841 { Xdecor_8, EL_EMC_WALL_1 },
4842 { Xdecor_9, EL_EMC_WALL_2 },
4843 { Xdecor_10, EL_EMC_WALL_3 },
4844 { Xdecor_11, EL_UNKNOWN },
4845 { Xdecor_12, EL_UNKNOWN },
4846 { Xalpha_0, EL_CHAR('0') },
4847 { Xalpha_1, EL_CHAR('1') },
4848 { Xalpha_2, EL_CHAR('2') },
4849 { Xalpha_3, EL_CHAR('3') },
4850 { Xalpha_4, EL_CHAR('4') },
4851 { Xalpha_5, EL_CHAR('5') },
4852 { Xalpha_6, EL_CHAR('6') },
4853 { Xalpha_7, EL_CHAR('7') },
4854 { Xalpha_8, EL_CHAR('8') },
4855 { Xalpha_9, EL_CHAR('9') },
4856 { Xalpha_excla, EL_CHAR('!') },
4857 { Xalpha_quote, EL_CHAR('"') },
4858 { Xalpha_comma, EL_CHAR(',') },
4859 { Xalpha_minus, EL_CHAR('-') },
4860 { Xalpha_perio, EL_CHAR('.') },
4861 { Xalpha_colon, EL_CHAR(':') },
4862 { Xalpha_quest, EL_CHAR('?') },
4863 { Xalpha_a, EL_CHAR('A') },
4864 { Xalpha_b, EL_CHAR('B') },
4865 { Xalpha_c, EL_CHAR('C') },
4866 { Xalpha_d, EL_CHAR('D') },
4867 { Xalpha_e, EL_CHAR('E') },
4868 { Xalpha_f, EL_CHAR('F') },
4869 { Xalpha_g, EL_CHAR('G') },
4870 { Xalpha_h, EL_CHAR('H') },
4871 { Xalpha_i, EL_CHAR('I') },
4872 { Xalpha_j, EL_CHAR('J') },
4873 { Xalpha_k, EL_CHAR('K') },
4874 { Xalpha_l, EL_CHAR('L') },
4875 { Xalpha_m, EL_CHAR('M') },
4876 { Xalpha_n, EL_CHAR('N') },
4877 { Xalpha_o, EL_CHAR('O') },
4878 { Xalpha_p, EL_CHAR('P') },
4879 { Xalpha_q, EL_CHAR('Q') },
4880 { Xalpha_r, EL_CHAR('R') },
4881 { Xalpha_s, EL_CHAR('S') },
4882 { Xalpha_t, EL_CHAR('T') },
4883 { Xalpha_u, EL_CHAR('U') },
4884 { Xalpha_v, EL_CHAR('V') },
4885 { Xalpha_w, EL_CHAR('W') },
4886 { Xalpha_x, EL_CHAR('X') },
4887 { Xalpha_y, EL_CHAR('Y') },
4888 { Xalpha_z, EL_CHAR('Z') },
4889 { Xalpha_arrow_e, EL_CHAR('>') },
4890 { Xalpha_arrow_w, EL_CHAR('<') },
4891 { Xalpha_copyr, EL_CHAR('©') },
4893 { Zplayer, EL_PLAYER_1 },
4894 { Zplayer, EL_PLAYER_2 },
4895 { Zplayer, EL_PLAYER_3 },
4896 { Zplayer, EL_PLAYER_4 },
4898 { ZBORDER, EL_EMC_LEVEL_BORDER },
4903 if (!mapping_initialized)
4907 /* return "Xalpha_quest" for all undefined elements in mapping array */
4908 for (i = 0; i < NUM_FILE_ELEMENTS; i++)
4909 mapping_RND_to_EM[i] = Xalpha_quest;
4911 for (i = 0; mapping_RND_to_EM_list[i].element_rnd != -1; i++)
4912 mapping_RND_to_EM[mapping_RND_to_EM_list[i].element_rnd] =
4913 mapping_RND_to_EM_list[i].element_em;
4915 mapping_initialized = TRUE;
4918 if (element_rnd >= 0 && element_rnd < NUM_FILE_ELEMENTS)
4919 return mapping_RND_to_EM[element_rnd];
4921 Error(ERR_WARN, "invalid RND level element %d", element_rnd);
4926 int map_element_EM_to_RND(int element_em)
4928 static unsigned short mapping_EM_to_RND[TILE_MAX];
4929 static boolean mapping_initialized = FALSE;
4936 em_object_mapping_list[] =
4938 { Xblank, EL_EMPTY },
4939 { Yacid_splash_eB, EL_EMPTY },
4940 { Yacid_splash_wB, EL_EMPTY },
4942 #ifdef EM_ENGINE_BAD_ROLL
4943 { Xstone_force_e, EL_ROCK },
4944 { Xstone_force_w, EL_ROCK },
4945 { Xnut_force_e, EL_NUT },
4946 { Xnut_force_w, EL_NUT },
4947 { Xspring_force_e, EL_SPRING },
4948 { Xspring_force_w, EL_SPRING },
4949 { Xemerald_force_e, EL_EMERALD },
4950 { Xemerald_force_w, EL_EMERALD },
4951 { Xdiamond_force_e, EL_DIAMOND },
4952 { Xdiamond_force_w, EL_DIAMOND },
4953 { Xbomb_force_e, EL_BOMB },
4954 { Xbomb_force_w, EL_BOMB },
4957 { Xstone, EL_ROCK },
4958 { Xstone_pause, EL_ROCK },
4959 { Xstone_fall, EL_ROCK },
4960 { Ystone_s, EL_ROCK },
4961 { Ystone_sB, EL_ROCK },
4962 { Ystone_e, EL_ROCK },
4963 { Ystone_eB, EL_ROCK },
4964 { Ystone_w, EL_ROCK },
4965 { Ystone_wB, EL_ROCK },
4967 { Xnut_pause, EL_NUT },
4968 { Xnut_fall, EL_NUT },
4970 { Ynut_sB, EL_NUT },
4972 { Ynut_eB, EL_NUT },
4974 { Ynut_wB, EL_NUT },
4975 { Xbug_n, EL_BUG_UP },
4976 { Xbug_e, EL_BUG_RIGHT },
4977 { Xbug_s, EL_BUG_DOWN },
4978 { Xbug_w, EL_BUG_LEFT },
4979 { Xbug_gon, EL_BUG_UP },
4980 { Xbug_goe, EL_BUG_RIGHT },
4981 { Xbug_gos, EL_BUG_DOWN },
4982 { Xbug_gow, EL_BUG_LEFT },
4983 { Ybug_n, EL_BUG_UP },
4984 { Ybug_nB, EL_BUG_UP },
4985 { Ybug_e, EL_BUG_RIGHT },
4986 { Ybug_eB, EL_BUG_RIGHT },
4987 { Ybug_s, EL_BUG_DOWN },
4988 { Ybug_sB, EL_BUG_DOWN },
4989 { Ybug_w, EL_BUG_LEFT },
4990 { Ybug_wB, EL_BUG_LEFT },
4991 { Ybug_w_n, EL_BUG_UP },
4992 { Ybug_n_e, EL_BUG_RIGHT },
4993 { Ybug_e_s, EL_BUG_DOWN },
4994 { Ybug_s_w, EL_BUG_LEFT },
4995 { Ybug_e_n, EL_BUG_UP },
4996 { Ybug_s_e, EL_BUG_RIGHT },
4997 { Ybug_w_s, EL_BUG_DOWN },
4998 { Ybug_n_w, EL_BUG_LEFT },
4999 { Ybug_stone, EL_ROCK },
5000 { Ybug_spring, EL_SPRING },
5001 { Xtank_n, EL_SPACESHIP_UP },
5002 { Xtank_e, EL_SPACESHIP_RIGHT },
5003 { Xtank_s, EL_SPACESHIP_DOWN },
5004 { Xtank_w, EL_SPACESHIP_LEFT },
5005 { Xtank_gon, EL_SPACESHIP_UP },
5006 { Xtank_goe, EL_SPACESHIP_RIGHT },
5007 { Xtank_gos, EL_SPACESHIP_DOWN },
5008 { Xtank_gow, EL_SPACESHIP_LEFT },
5009 { Ytank_n, EL_SPACESHIP_UP },
5010 { Ytank_nB, EL_SPACESHIP_UP },
5011 { Ytank_e, EL_SPACESHIP_RIGHT },
5012 { Ytank_eB, EL_SPACESHIP_RIGHT },
5013 { Ytank_s, EL_SPACESHIP_DOWN },
5014 { Ytank_sB, EL_SPACESHIP_DOWN },
5015 { Ytank_w, EL_SPACESHIP_LEFT },
5016 { Ytank_wB, EL_SPACESHIP_LEFT },
5017 { Ytank_w_n, EL_SPACESHIP_UP },
5018 { Ytank_n_e, EL_SPACESHIP_RIGHT },
5019 { Ytank_e_s, EL_SPACESHIP_DOWN },
5020 { Ytank_s_w, EL_SPACESHIP_LEFT },
5021 { Ytank_e_n, EL_SPACESHIP_UP },
5022 { Ytank_s_e, EL_SPACESHIP_RIGHT },
5023 { Ytank_w_s, EL_SPACESHIP_DOWN },
5024 { Ytank_n_w, EL_SPACESHIP_LEFT },
5025 { Ytank_stone, EL_ROCK },
5026 { Ytank_spring, EL_SPRING },
5027 { Xandroid, EL_EMC_ANDROID },
5028 { Xandroid_1_n, EL_EMC_ANDROID_UP },
5029 { Xandroid_2_n, EL_EMC_ANDROID_UP },
5030 { Xandroid_1_e, EL_EMC_ANDROID_RIGHT },
5031 { Xandroid_2_e, EL_EMC_ANDROID_RIGHT },
5032 { Xandroid_1_w, EL_EMC_ANDROID_LEFT },
5033 { Xandroid_2_w, EL_EMC_ANDROID_LEFT },
5034 { Xandroid_1_s, EL_EMC_ANDROID_DOWN },
5035 { Xandroid_2_s, EL_EMC_ANDROID_DOWN },
5036 { Yandroid_n, EL_EMC_ANDROID_UP },
5037 { Yandroid_nB, EL_EMC_ANDROID_UP },
5038 { Yandroid_ne, EL_EMC_ANDROID_RIGHT_UP },
5039 { Yandroid_neB, EL_EMC_ANDROID_RIGHT_UP },
5040 { Yandroid_e, EL_EMC_ANDROID_RIGHT },
5041 { Yandroid_eB, EL_EMC_ANDROID_RIGHT },
5042 { Yandroid_se, EL_EMC_ANDROID_RIGHT_DOWN },
5043 { Yandroid_seB, EL_EMC_ANDROID_RIGHT_DOWN },
5044 { Yandroid_s, EL_EMC_ANDROID_DOWN },
5045 { Yandroid_sB, EL_EMC_ANDROID_DOWN },
5046 { Yandroid_sw, EL_EMC_ANDROID_LEFT_DOWN },
5047 { Yandroid_swB, EL_EMC_ANDROID_LEFT_DOWN },
5048 { Yandroid_w, EL_EMC_ANDROID_LEFT },
5049 { Yandroid_wB, EL_EMC_ANDROID_LEFT },
5050 { Yandroid_nw, EL_EMC_ANDROID_LEFT_UP },
5051 { Yandroid_nwB, EL_EMC_ANDROID_LEFT_UP },
5052 { Xspring, EL_SPRING },
5053 { Xspring_pause, EL_SPRING },
5054 { Xspring_e, EL_SPRING },
5055 { Xspring_w, EL_SPRING },
5056 { Xspring_fall, EL_SPRING },
5057 { Yspring_s, EL_SPRING },
5058 { Yspring_sB, EL_SPRING },
5059 { Yspring_e, EL_SPRING },
5060 { Yspring_eB, EL_SPRING },
5061 { Yspring_w, EL_SPRING },
5062 { Yspring_wB, EL_SPRING },
5063 { Yspring_kill_e, EL_SPRING },
5064 { Yspring_kill_eB, EL_SPRING },
5065 { Yspring_kill_w, EL_SPRING },
5066 { Yspring_kill_wB, EL_SPRING },
5067 { Xeater_n, EL_YAMYAM },
5068 { Xeater_e, EL_YAMYAM },
5069 { Xeater_w, EL_YAMYAM },
5070 { Xeater_s, EL_YAMYAM },
5071 { Yeater_n, EL_YAMYAM },
5072 { Yeater_nB, EL_YAMYAM },
5073 { Yeater_e, EL_YAMYAM },
5074 { Yeater_eB, EL_YAMYAM },
5075 { Yeater_s, EL_YAMYAM },
5076 { Yeater_sB, EL_YAMYAM },
5077 { Yeater_w, EL_YAMYAM },
5078 { Yeater_wB, EL_YAMYAM },
5079 { Yeater_stone, EL_ROCK },
5080 { Yeater_spring, EL_SPRING },
5081 { Xalien, EL_ROBOT },
5082 { Xalien_pause, EL_ROBOT },
5083 { Yalien_n, EL_ROBOT },
5084 { Yalien_nB, EL_ROBOT },
5085 { Yalien_e, EL_ROBOT },
5086 { Yalien_eB, EL_ROBOT },
5087 { Yalien_s, EL_ROBOT },
5088 { Yalien_sB, EL_ROBOT },
5089 { Yalien_w, EL_ROBOT },
5090 { Yalien_wB, EL_ROBOT },
5091 { Yalien_stone, EL_ROCK },
5092 { Yalien_spring, EL_SPRING },
5093 { Xemerald, EL_EMERALD },
5094 { Xemerald_pause, EL_EMERALD },
5095 { Xemerald_fall, EL_EMERALD },
5096 { Xemerald_shine, EL_EMERALD },
5097 { Yemerald_s, EL_EMERALD },
5098 { Yemerald_sB, EL_EMERALD },
5099 { Yemerald_e, EL_EMERALD },
5100 { Yemerald_eB, EL_EMERALD },
5101 { Yemerald_w, EL_EMERALD },
5102 { Yemerald_wB, EL_EMERALD },
5103 { Yemerald_eat, EL_EMERALD },
5104 { Yemerald_stone, EL_ROCK },
5105 { Xdiamond, EL_DIAMOND },
5106 { Xdiamond_pause, EL_DIAMOND },
5107 { Xdiamond_fall, EL_DIAMOND },
5108 { Xdiamond_shine, EL_DIAMOND },
5109 { Ydiamond_s, EL_DIAMOND },
5110 { Ydiamond_sB, EL_DIAMOND },
5111 { Ydiamond_e, EL_DIAMOND },
5112 { Ydiamond_eB, EL_DIAMOND },
5113 { Ydiamond_w, EL_DIAMOND },
5114 { Ydiamond_wB, EL_DIAMOND },
5115 { Ydiamond_eat, EL_DIAMOND },
5116 { Ydiamond_stone, EL_ROCK },
5117 { Xdrip_fall, EL_AMOEBA_DROP },
5118 { Xdrip_stretch, EL_AMOEBA_DROP },
5119 { Xdrip_stretchB, EL_AMOEBA_DROP },
5120 { Xdrip_eat, EL_AMOEBA_DROP },
5121 { Ydrip_s1, EL_AMOEBA_DROP },
5122 { Ydrip_s1B, EL_AMOEBA_DROP },
5123 { Ydrip_s2, EL_AMOEBA_DROP },
5124 { Ydrip_s2B, EL_AMOEBA_DROP },
5126 { Xbomb_pause, EL_BOMB },
5127 { Xbomb_fall, EL_BOMB },
5128 { Ybomb_s, EL_BOMB },
5129 { Ybomb_sB, EL_BOMB },
5130 { Ybomb_e, EL_BOMB },
5131 { Ybomb_eB, EL_BOMB },
5132 { Ybomb_w, EL_BOMB },
5133 { Ybomb_wB, EL_BOMB },
5134 { Ybomb_eat, EL_BOMB },
5135 { Xballoon, EL_BALLOON },
5136 { Yballoon_n, EL_BALLOON },
5137 { Yballoon_nB, EL_BALLOON },
5138 { Yballoon_e, EL_BALLOON },
5139 { Yballoon_eB, EL_BALLOON },
5140 { Yballoon_s, EL_BALLOON },
5141 { Yballoon_sB, EL_BALLOON },
5142 { Yballoon_w, EL_BALLOON },
5143 { Yballoon_wB, EL_BALLOON },
5144 { Xgrass, EL_SAND },
5145 { Ygrass_nB, EL_SAND },
5146 { Ygrass_eB, EL_SAND },
5147 { Ygrass_sB, EL_SAND },
5148 { Ygrass_wB, EL_SAND },
5150 { Ydirt_nB, EL_SAND },
5151 { Ydirt_eB, EL_SAND },
5152 { Ydirt_sB, EL_SAND },
5153 { Ydirt_wB, EL_SAND },
5154 { Xacid_ne, EL_ACID_POOL_TOPRIGHT },
5155 { Xacid_se, EL_ACID_POOL_BOTTOMRIGHT },
5156 { Xacid_s, EL_ACID_POOL_BOTTOM },
5157 { Xacid_sw, EL_ACID_POOL_BOTTOMLEFT },
5158 { Xacid_nw, EL_ACID_POOL_TOPLEFT },
5159 { Xacid_1, EL_ACID },
5160 { Xacid_2, EL_ACID },
5161 { Xacid_3, EL_ACID },
5162 { Xacid_4, EL_ACID },
5163 { Xacid_5, EL_ACID },
5164 { Xacid_6, EL_ACID },
5165 { Xacid_7, EL_ACID },
5166 { Xacid_8, EL_ACID },
5167 { Xball_1, EL_EMC_MAGIC_BALL },
5168 { Xball_1B, EL_EMC_MAGIC_BALL },
5169 { Xball_2, EL_EMC_MAGIC_BALL },
5170 { Xball_2B, EL_EMC_MAGIC_BALL },
5171 { Yball_eat, EL_EMC_MAGIC_BALL },
5172 { Xgrow_ns, EL_EMC_GROW },
5173 { Ygrow_ns_eat, EL_EMC_GROW },
5174 { Xgrow_ew, EL_EMC_GROW },
5175 { Ygrow_ew_eat, EL_EMC_GROW },
5176 { Xwonderwall, EL_MAGIC_WALL },
5177 { XwonderwallB, EL_MAGIC_WALL },
5178 { Xamoeba_1, EL_AMOEBA_WET },
5179 { Xamoeba_2, EL_AMOEBA_WET },
5180 { Xamoeba_3, EL_AMOEBA_WET },
5181 { Xamoeba_4, EL_AMOEBA_WET },
5182 { Xamoeba_5, EL_AMOEBA_WET },
5183 { Xamoeba_6, EL_AMOEBA_WET },
5184 { Xamoeba_7, EL_AMOEBA_WET },
5185 { Xamoeba_8, EL_AMOEBA_WET },
5186 { Xdoor_1, EL_EM_GATE_1 },
5187 { Xdoor_2, EL_EM_GATE_2 },
5188 { Xdoor_3, EL_EM_GATE_3 },
5189 { Xdoor_4, EL_EM_GATE_4 },
5190 { Xdoor_5, EL_EMC_GATE_5 },
5191 { Xdoor_6, EL_EMC_GATE_6 },
5192 { Xdoor_7, EL_EMC_GATE_7 },
5193 { Xdoor_8, EL_EMC_GATE_8 },
5194 { Xkey_1, EL_EM_KEY_1 },
5195 { Xkey_2, EL_EM_KEY_2 },
5196 { Xkey_3, EL_EM_KEY_3 },
5197 { Xkey_4, EL_EM_KEY_4 },
5198 { Xkey_5, EL_EMC_KEY_5 },
5199 { Xkey_6, EL_EMC_KEY_6 },
5200 { Xkey_7, EL_EMC_KEY_7 },
5201 { Xkey_8, EL_EMC_KEY_8 },
5202 { Xwind_n, EL_BALLOON_SWITCH_UP },
5203 { Xwind_e, EL_BALLOON_SWITCH_RIGHT },
5204 { Xwind_s, EL_BALLOON_SWITCH_DOWN },
5205 { Xwind_w, EL_BALLOON_SWITCH_LEFT },
5206 { Xwind_nesw, EL_BALLOON_SWITCH_ANY },
5207 { Xwind_stop, EL_BALLOON_SWITCH_NONE },
5208 { Xexit, EL_EXIT_CLOSED },
5209 { Xexit_1, EL_EXIT_OPEN },
5210 { Xexit_2, EL_EXIT_OPEN },
5211 { Xexit_3, EL_EXIT_OPEN },
5212 { Xdynamite, EL_DYNAMITE },
5213 { Ydynamite_eat, EL_DYNAMITE },
5214 { Xdynamite_1, EL_DYNAMITE_ACTIVE },
5215 { Xdynamite_2, EL_DYNAMITE_ACTIVE },
5216 { Xdynamite_3, EL_DYNAMITE_ACTIVE },
5217 { Xdynamite_4, EL_DYNAMITE_ACTIVE },
5218 { Xbumper, EL_EMC_BUMPER },
5219 { XbumperB, EL_EMC_BUMPER },
5220 { Xwheel, EL_ROBOT_WHEEL },
5221 { XwheelB, EL_ROBOT_WHEEL },
5222 { Xswitch, EL_UNKNOWN },
5223 { XswitchB, EL_UNKNOWN },
5224 { Xsand, EL_QUICKSAND_EMPTY },
5225 { Xsand_stone, EL_QUICKSAND_FULL },
5226 { Xsand_stonein_1, EL_QUICKSAND_FULL },
5227 { Xsand_stonein_2, EL_QUICKSAND_FULL },
5228 { Xsand_stonein_3, EL_QUICKSAND_FULL },
5229 { Xsand_stonein_4, EL_QUICKSAND_FULL },
5230 { Xsand_stonesand_1, EL_QUICKSAND_FULL },
5231 { Xsand_stonesand_2, EL_QUICKSAND_FULL },
5232 { Xsand_stonesand_3, EL_QUICKSAND_FULL },
5233 { Xsand_stonesand_4, EL_QUICKSAND_FULL },
5234 { Xsand_stoneout_1, EL_QUICKSAND_FULL },
5235 { Xsand_stoneout_2, EL_QUICKSAND_FULL },
5236 { Xsand_sandstone_1, EL_QUICKSAND_FULL },
5237 { Xsand_sandstone_2, EL_QUICKSAND_FULL },
5238 { Xsand_sandstone_3, EL_QUICKSAND_FULL },
5239 { Xsand_sandstone_4, EL_QUICKSAND_FULL },
5240 { Xplant, EL_EMC_PLANT },
5241 { Yplant, EL_EMC_PLANT },
5242 { Xlenses, EL_EMC_LENSES },
5243 { Xmagnify, EL_EMC_MAGNIFIER },
5244 { Xdripper, EL_UNKNOWN },
5245 { XdripperB, EL_UNKNOWN },
5246 { Xfake_blank, EL_INVISIBLE_WALL },
5247 { Xfake_blankB, EL_INVISIBLE_WALL },
5248 { Xfake_grass, EL_INVISIBLE_SAND },
5249 { Xfake_grassB, EL_INVISIBLE_SAND },
5250 { Xfake_door_1, EL_EM_GATE_1_GRAY },
5251 { Xfake_door_2, EL_EM_GATE_2_GRAY },
5252 { Xfake_door_3, EL_EM_GATE_3_GRAY },
5253 { Xfake_door_4, EL_EM_GATE_4_GRAY },
5254 { Xfake_door_5, EL_EMC_GATE_5_GRAY },
5255 { Xfake_door_6, EL_EMC_GATE_6_GRAY },
5256 { Xfake_door_7, EL_EMC_GATE_7_GRAY },
5257 { Xfake_door_8, EL_EMC_GATE_8_GRAY },
5258 { Xsteel_1, EL_STEELWALL },
5259 { Xsteel_2, EL_UNKNOWN },
5260 { Xsteel_3, EL_EMC_STEELWALL_1 },
5261 { Xsteel_4, EL_UNKNOWN },
5262 { Xwall_1, EL_WALL },
5263 { Xwall_2, EL_UNKNOWN },
5264 { Xwall_3, EL_UNKNOWN },
5265 { Xwall_4, EL_UNKNOWN },
5266 { Xround_wall_1, EL_WALL_SLIPPERY },
5267 { Xround_wall_2, EL_UNKNOWN },
5268 { Xround_wall_3, EL_UNKNOWN },
5269 { Xround_wall_4, EL_UNKNOWN },
5270 { Xdecor_1, EL_UNKNOWN },
5271 { Xdecor_2, EL_EMC_WALL_6 },
5272 { Xdecor_3, EL_EMC_WALL_4 },
5273 { Xdecor_4, EL_EMC_WALL_5 },
5274 { Xdecor_5, EL_EMC_WALL_7 },
5275 { Xdecor_6, EL_EMC_WALL_8 },
5276 { Xdecor_7, EL_UNKNOWN },
5277 { Xdecor_8, EL_EMC_WALL_1 },
5278 { Xdecor_9, EL_EMC_WALL_2 },
5279 { Xdecor_10, EL_EMC_WALL_3 },
5280 { Xdecor_11, EL_UNKNOWN },
5281 { Xdecor_12, EL_UNKNOWN },
5282 { Xalpha_0, EL_CHAR('0') },
5283 { Xalpha_1, EL_CHAR('1') },
5284 { Xalpha_2, EL_CHAR('2') },
5285 { Xalpha_3, EL_CHAR('3') },
5286 { Xalpha_4, EL_CHAR('4') },
5287 { Xalpha_5, EL_CHAR('5') },
5288 { Xalpha_6, EL_CHAR('6') },
5289 { Xalpha_7, EL_CHAR('7') },
5290 { Xalpha_8, EL_CHAR('8') },
5291 { Xalpha_9, EL_CHAR('9') },
5292 { Xalpha_excla, EL_CHAR('!') },
5293 { Xalpha_quote, EL_CHAR('"') },
5294 { Xalpha_comma, EL_CHAR(',') },
5295 { Xalpha_minus, EL_CHAR('-') },
5296 { Xalpha_perio, EL_CHAR('.') },
5297 { Xalpha_colon, EL_CHAR(':') },
5298 { Xalpha_quest, EL_CHAR('?') },
5299 { Xalpha_a, EL_CHAR('A') },
5300 { Xalpha_b, EL_CHAR('B') },
5301 { Xalpha_c, EL_CHAR('C') },
5302 { Xalpha_d, EL_CHAR('D') },
5303 { Xalpha_e, EL_CHAR('E') },
5304 { Xalpha_f, EL_CHAR('F') },
5305 { Xalpha_g, EL_CHAR('G') },
5306 { Xalpha_h, EL_CHAR('H') },
5307 { Xalpha_i, EL_CHAR('I') },
5308 { Xalpha_j, EL_CHAR('J') },
5309 { Xalpha_k, EL_CHAR('K') },
5310 { Xalpha_l, EL_CHAR('L') },
5311 { Xalpha_m, EL_CHAR('M') },
5312 { Xalpha_n, EL_CHAR('N') },
5313 { Xalpha_o, EL_CHAR('O') },
5314 { Xalpha_p, EL_CHAR('P') },
5315 { Xalpha_q, EL_CHAR('Q') },
5316 { Xalpha_r, EL_CHAR('R') },
5317 { Xalpha_s, EL_CHAR('S') },
5318 { Xalpha_t, EL_CHAR('T') },
5319 { Xalpha_u, EL_CHAR('U') },
5320 { Xalpha_v, EL_CHAR('V') },
5321 { Xalpha_w, EL_CHAR('W') },
5322 { Xalpha_x, EL_CHAR('X') },
5323 { Xalpha_y, EL_CHAR('Y') },
5324 { Xalpha_z, EL_CHAR('Z') },
5325 { Xalpha_arrow_e, EL_CHAR('>') },
5326 { Xalpha_arrow_w, EL_CHAR('<') },
5327 { Xalpha_copyr, EL_CHAR('©') },
5329 { Zplayer, EL_PLAYER_1 },
5331 { ZBORDER, EL_EMC_LEVEL_BORDER },
5336 if (!mapping_initialized)
5340 /* return "EL_UNKNOWN" for all undefined elements in mapping array */
5341 for (i = 0; i < TILE_MAX; i++)
5342 mapping_EM_to_RND[i] = EL_UNKNOWN;
5344 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
5345 mapping_EM_to_RND[em_object_mapping_list[i].element_em] =
5346 em_object_mapping_list[i].element_rnd;
5348 mapping_initialized = TRUE;
5351 if (element_em >= 0 && element_em < TILE_MAX)
5352 return mapping_EM_to_RND[element_em];
5354 Error(ERR_WARN, "invalid EM level element %d", element_em);
5361 int get_next_element(int element)
5365 case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL;
5366 case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY;
5367 case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL;
5368 case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_ACTIVE;
5369 case EL_BD_MAGIC_WALL_FILLING: return EL_BD_MAGIC_WALL_FULL;
5370 case EL_BD_MAGIC_WALL_EMPTYING: return EL_BD_MAGIC_WALL_ACTIVE;
5371 case EL_AMOEBA_DROPPING: return EL_AMOEBA_WET;
5373 default: return element;
5378 int el_act_dir2img(int element, int action, int direction)
5380 element = GFX_ELEMENT(element);
5382 if (direction == MV_NO_MOVING)
5383 return element_info[element].graphic[action];
5385 direction = MV_DIR_BIT(direction);
5387 return element_info[element].direction_graphic[action][direction];
5390 int el_act_dir2img(int element, int action, int direction)
5392 element = GFX_ELEMENT(element);
5393 direction = MV_DIR_BIT(direction); /* default: MV_NO_MOVING => MV_DOWN */
5395 /* direction_graphic[][] == graphic[] for undefined direction graphics */
5396 return element_info[element].direction_graphic[action][direction];
5401 static int el_act_dir2crm(int element, int action, int direction)
5403 element = GFX_ELEMENT(element);
5405 if (direction == MV_NO_MOVING)
5406 return element_info[element].crumbled[action];
5408 direction = MV_DIR_BIT(direction);
5410 return element_info[element].direction_crumbled[action][direction];
5413 static int el_act_dir2crm(int element, int action, int direction)
5415 element = GFX_ELEMENT(element);
5416 direction = MV_DIR_BIT(direction); /* default: MV_NO_MOVING => MV_DOWN */
5418 /* direction_graphic[][] == graphic[] for undefined direction graphics */
5419 return element_info[element].direction_crumbled[action][direction];
5423 int el_act2img(int element, int action)
5425 element = GFX_ELEMENT(element);
5427 return element_info[element].graphic[action];
5430 int el_act2crm(int element, int action)
5432 element = GFX_ELEMENT(element);
5434 return element_info[element].crumbled[action];
5437 int el_dir2img(int element, int direction)
5439 element = GFX_ELEMENT(element);
5441 return el_act_dir2img(element, ACTION_DEFAULT, direction);
5444 int el2baseimg(int element)
5446 return element_info[element].graphic[ACTION_DEFAULT];
5449 int el2img(int element)
5451 element = GFX_ELEMENT(element);
5453 return element_info[element].graphic[ACTION_DEFAULT];
5456 int el2edimg(int element)
5458 element = GFX_ELEMENT(element);
5460 return element_info[element].special_graphic[GFX_SPECIAL_ARG_EDITOR];
5463 int el2preimg(int element)
5465 element = GFX_ELEMENT(element);
5467 return element_info[element].special_graphic[GFX_SPECIAL_ARG_PREVIEW];
5470 int getGameFrameDelay_EM(int native_em_game_frame_delay)
5472 int game_frame_delay_value;
5474 game_frame_delay_value =
5475 (tape.playing && tape.fast_forward ? FfwdFrameDelay :
5476 GameFrameDelay == GAME_FRAME_DELAY ? native_em_game_frame_delay :
5479 if (tape.playing && tape.warp_forward && !tape.pausing)
5480 game_frame_delay_value = 0;
5482 return game_frame_delay_value;
5485 unsigned int InitRND(long seed)
5487 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
5488 return InitEngineRND_EM(seed);
5490 return InitEngineRND(seed);
5493 #define DEBUG_EM_GFX 0
5495 void InitGraphicInfo_EM(void)
5497 struct Mapping_EM_to_RND_object object_mapping[TILE_MAX];
5498 struct Mapping_EM_to_RND_player player_mapping[2][SPR_MAX];
5502 if (graphic_info_em_object[0][0].bitmap == NULL)
5504 /* EM graphics not yet initialized in em_open_all() */
5510 /* always start with reliable default values */
5511 for (i = 0; i < TILE_MAX; i++)
5513 object_mapping[i].element_rnd = EL_UNKNOWN;
5514 object_mapping[i].is_backside = FALSE;
5515 object_mapping[i].action = ACTION_DEFAULT;
5516 object_mapping[i].direction = MV_NO_MOVING;
5519 /* always start with reliable default values */
5520 for (p = 0; p < 2; p++)
5522 for (i = 0; i < SPR_MAX; i++)
5524 player_mapping[p][i].element_rnd = EL_UNKNOWN;
5525 player_mapping[p][i].action = ACTION_DEFAULT;
5526 player_mapping[p][i].direction = MV_NO_MOVING;
5530 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
5532 int e = em_object_mapping_list[i].element_em;
5534 object_mapping[e].element_rnd = em_object_mapping_list[i].element_rnd;
5535 object_mapping[e].is_backside = em_object_mapping_list[i].is_backside;
5537 if (em_object_mapping_list[i].action != -1)
5538 object_mapping[e].action = em_object_mapping_list[i].action;
5540 if (em_object_mapping_list[i].direction != -1)
5541 object_mapping[e].direction = (1 << em_object_mapping_list[i].direction);
5544 for (i = 0; em_player_mapping_list[i].action_em != -1; i++)
5546 int a = em_player_mapping_list[i].action_em;
5547 int p = em_player_mapping_list[i].player_nr;
5549 player_mapping[p][a].element_rnd = em_player_mapping_list[i].element_rnd;
5551 if (em_player_mapping_list[i].action != -1)
5552 player_mapping[p][a].action = em_player_mapping_list[i].action;
5554 if (em_player_mapping_list[i].direction != -1)
5555 player_mapping[p][a].direction =
5556 (1 << em_player_mapping_list[i].direction);
5559 for (i = 0; i < TILE_MAX; i++)
5561 int element = object_mapping[i].element_rnd;
5562 int action = object_mapping[i].action;
5563 int direction = object_mapping[i].direction;
5564 boolean is_backside = object_mapping[i].is_backside;
5565 boolean action_removing = (action == ACTION_DIGGING ||
5566 action == ACTION_SNAPPING ||
5567 action == ACTION_COLLECTING);
5568 boolean action_exploding = ((action == ACTION_EXPLODING ||
5569 action == ACTION_SMASHED_BY_ROCK ||
5570 action == ACTION_SMASHED_BY_SPRING) &&
5571 element != EL_DIAMOND);
5572 boolean action_active = (action == ACTION_ACTIVE);
5573 boolean action_other = (action == ACTION_OTHER);
5575 for (j = 0; j < 8; j++)
5577 int effective_element = (j > 5 && i == Yacid_splash_eB ? EL_EMPTY :
5578 j > 5 && i == Yacid_splash_wB ? EL_EMPTY :
5580 i == Xdrip_stretch ? element :
5581 i == Xdrip_stretchB ? element :
5582 i == Ydrip_s1 ? element :
5583 i == Ydrip_s1B ? element :
5584 i == Xball_1B ? element :
5585 i == Xball_2 ? element :
5586 i == Xball_2B ? element :
5587 i == Yball_eat ? element :
5588 i == Ykey_1_eat ? element :
5589 i == Ykey_2_eat ? element :
5590 i == Ykey_3_eat ? element :
5591 i == Ykey_4_eat ? element :
5592 i == Ykey_5_eat ? element :
5593 i == Ykey_6_eat ? element :
5594 i == Ykey_7_eat ? element :
5595 i == Ykey_8_eat ? element :
5596 i == Ylenses_eat ? element :
5597 i == Ymagnify_eat ? element :
5598 i == Ygrass_eat ? element :
5599 i == Ydirt_eat ? element :
5600 i == Yspring_kill_e ? EL_SPRING :
5601 i == Yspring_kill_w ? EL_SPRING :
5602 i == Yemerald_stone ? EL_EMERALD :
5603 i == Ydiamond_stone ? EL_ROCK :
5604 i == Xsand_stonein_4 ? EL_EMPTY :
5605 i == Xsand_stoneout_2 ? EL_ROCK :
5606 is_backside ? EL_EMPTY :
5607 action_removing ? EL_EMPTY :
5609 int effective_action = (j < 7 ? action :
5610 i == Xdrip_stretch ? action :
5611 i == Xdrip_stretchB ? action :
5612 i == Ydrip_s1 ? action :
5613 i == Ydrip_s1B ? action :
5614 i == Xball_1B ? action :
5615 i == Xball_2 ? action :
5616 i == Xball_2B ? action :
5617 i == Yball_eat ? action :
5618 i == Ykey_1_eat ? action :
5619 i == Ykey_2_eat ? action :
5620 i == Ykey_3_eat ? action :
5621 i == Ykey_4_eat ? action :
5622 i == Ykey_5_eat ? action :
5623 i == Ykey_6_eat ? action :
5624 i == Ykey_7_eat ? action :
5625 i == Ykey_8_eat ? action :
5626 i == Ylenses_eat ? action :
5627 i == Ymagnify_eat ? action :
5628 i == Ygrass_eat ? action :
5629 i == Ydirt_eat ? action :
5630 i == Xsand_stonein_1 ? action :
5631 i == Xsand_stonein_2 ? action :
5632 i == Xsand_stonein_3 ? action :
5633 i == Xsand_stonein_4 ? action :
5634 i == Xsand_stoneout_1 ? action :
5635 i == Xsand_stoneout_2 ? action :
5636 i == Xboom_android ? ACTION_EXPLODING :
5637 action_exploding ? ACTION_EXPLODING :
5638 action_active ? action :
5639 action_other ? action :
5641 int graphic = (el_act_dir2img(effective_element, effective_action,
5643 int crumbled = (el_act_dir2crm(effective_element, effective_action,
5645 int base_graphic = el_act2img(effective_element, ACTION_DEFAULT);
5646 int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT);
5647 boolean has_crumbled_graphics = (base_crumbled != base_graphic);
5648 struct GraphicInfo *g = &graphic_info[graphic];
5649 struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
5652 /* ensure to get symmetric 3-frame, 2-delay animations as used in EM */
5653 boolean special_animation = (action != ACTION_DEFAULT &&
5654 g->anim_frames == 3 &&
5655 g->anim_delay == 2 &&
5656 g->anim_mode & ANIM_LINEAR);
5657 int sync_frame = (i == Xdrip_stretch ? 7 :
5658 i == Xdrip_stretchB ? 7 :
5659 i == Ydrip_s2 ? j + 8 :
5660 i == Ydrip_s2B ? j + 8 :
5669 i == Xfake_acid_1 ? 0 :
5670 i == Xfake_acid_2 ? 10 :
5671 i == Xfake_acid_3 ? 20 :
5672 i == Xfake_acid_4 ? 30 :
5673 i == Xfake_acid_5 ? 40 :
5674 i == Xfake_acid_6 ? 50 :
5675 i == Xfake_acid_7 ? 60 :
5676 i == Xfake_acid_8 ? 70 :
5678 i == Xball_2B ? j + 8 :
5679 i == Yball_eat ? j + 1 :
5680 i == Ykey_1_eat ? j + 1 :
5681 i == Ykey_2_eat ? j + 1 :
5682 i == Ykey_3_eat ? j + 1 :
5683 i == Ykey_4_eat ? j + 1 :
5684 i == Ykey_5_eat ? j + 1 :
5685 i == Ykey_6_eat ? j + 1 :
5686 i == Ykey_7_eat ? j + 1 :
5687 i == Ykey_8_eat ? j + 1 :
5688 i == Ylenses_eat ? j + 1 :
5689 i == Ymagnify_eat ? j + 1 :
5690 i == Ygrass_eat ? j + 1 :
5691 i == Ydirt_eat ? j + 1 :
5692 i == Xamoeba_1 ? 0 :
5693 i == Xamoeba_2 ? 1 :
5694 i == Xamoeba_3 ? 2 :
5695 i == Xamoeba_4 ? 3 :
5696 i == Xamoeba_5 ? 0 :
5697 i == Xamoeba_6 ? 1 :
5698 i == Xamoeba_7 ? 2 :
5699 i == Xamoeba_8 ? 3 :
5700 i == Xexit_2 ? j + 8 :
5701 i == Xexit_3 ? j + 16 :
5702 i == Xdynamite_1 ? 0 :
5703 i == Xdynamite_2 ? 20 :
5704 i == Xdynamite_3 ? 40 :
5705 i == Xdynamite_4 ? 60 :
5706 i == Xsand_stonein_1 ? j + 1 :
5707 i == Xsand_stonein_2 ? j + 9 :
5708 i == Xsand_stonein_3 ? j + 17 :
5709 i == Xsand_stonein_4 ? j + 25 :
5710 i == Xsand_stoneout_1 && j == 0 ? 0 :
5711 i == Xsand_stoneout_1 && j == 1 ? 0 :
5712 i == Xsand_stoneout_1 && j == 2 ? 1 :
5713 i == Xsand_stoneout_1 && j == 3 ? 2 :
5714 i == Xsand_stoneout_1 && j == 4 ? 2 :
5715 i == Xsand_stoneout_1 && j == 5 ? 3 :
5716 i == Xsand_stoneout_1 && j == 6 ? 4 :
5717 i == Xsand_stoneout_1 && j == 7 ? 4 :
5718 i == Xsand_stoneout_2 && j == 0 ? 5 :
5719 i == Xsand_stoneout_2 && j == 1 ? 6 :
5720 i == Xsand_stoneout_2 && j == 2 ? 7 :
5721 i == Xsand_stoneout_2 && j == 3 ? 8 :
5722 i == Xsand_stoneout_2 && j == 4 ? 9 :
5723 i == Xsand_stoneout_2 && j == 5 ? 11 :
5724 i == Xsand_stoneout_2 && j == 6 ? 13 :
5725 i == Xsand_stoneout_2 && j == 7 ? 15 :
5726 i == Xboom_bug && j == 1 ? 2 :
5727 i == Xboom_bug && j == 2 ? 2 :
5728 i == Xboom_bug && j == 3 ? 4 :
5729 i == Xboom_bug && j == 4 ? 4 :
5730 i == Xboom_bug && j == 5 ? 2 :
5731 i == Xboom_bug && j == 6 ? 2 :
5732 i == Xboom_bug && j == 7 ? 0 :
5733 i == Xboom_bomb && j == 1 ? 2 :
5734 i == Xboom_bomb && j == 2 ? 2 :
5735 i == Xboom_bomb && j == 3 ? 4 :
5736 i == Xboom_bomb && j == 4 ? 4 :
5737 i == Xboom_bomb && j == 5 ? 2 :
5738 i == Xboom_bomb && j == 6 ? 2 :
5739 i == Xboom_bomb && j == 7 ? 0 :
5740 i == Xboom_android && j == 7 ? 6 :
5741 i == Xboom_1 && j == 1 ? 2 :
5742 i == Xboom_1 && j == 2 ? 2 :
5743 i == Xboom_1 && j == 3 ? 4 :
5744 i == Xboom_1 && j == 4 ? 4 :
5745 i == Xboom_1 && j == 5 ? 6 :
5746 i == Xboom_1 && j == 6 ? 6 :
5747 i == Xboom_1 && j == 7 ? 8 :
5748 i == Xboom_2 && j == 0 ? 8 :
5749 i == Xboom_2 && j == 1 ? 8 :
5750 i == Xboom_2 && j == 2 ? 10 :
5751 i == Xboom_2 && j == 3 ? 10 :
5752 i == Xboom_2 && j == 4 ? 10 :
5753 i == Xboom_2 && j == 5 ? 12 :
5754 i == Xboom_2 && j == 6 ? 12 :
5755 i == Xboom_2 && j == 7 ? 12 :
5756 special_animation && j == 4 ? 3 :
5757 effective_action != action ? 0 :
5761 Bitmap *debug_bitmap = g_em->bitmap;
5762 int debug_src_x = g_em->src_x;
5763 int debug_src_y = g_em->src_y;
5766 int frame = getAnimationFrame(g->anim_frames,
5769 g->anim_start_frame,
5772 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y,
5773 g->double_movement && is_backside);
5775 g_em->bitmap = src_bitmap;
5776 g_em->src_x = src_x;
5777 g_em->src_y = src_y;
5778 g_em->src_offset_x = 0;
5779 g_em->src_offset_y = 0;
5780 g_em->dst_offset_x = 0;
5781 g_em->dst_offset_y = 0;
5782 g_em->width = TILEX;
5783 g_em->height = TILEY;
5785 g_em->crumbled_bitmap = NULL;
5786 g_em->crumbled_src_x = 0;
5787 g_em->crumbled_src_y = 0;
5788 g_em->crumbled_border_size = 0;
5790 g_em->has_crumbled_graphics = FALSE;
5791 g_em->preserve_background = FALSE;
5794 if (has_crumbled_graphics && crumbled == IMG_EMPTY_SPACE)
5795 printf("::: empty crumbled: %d [%s], %d, %d\n",
5796 effective_element, element_info[effective_element].token_name,
5797 effective_action, direction);
5800 /* if element can be crumbled, but certain action graphics are just empty
5801 space (like snapping sand with the original R'n'D graphics), do not
5802 treat these empty space graphics as crumbled graphics in EMC engine */
5803 if (has_crumbled_graphics && crumbled != IMG_EMPTY_SPACE)
5805 getGraphicSource(crumbled, frame, &src_bitmap, &src_x, &src_y);
5807 g_em->has_crumbled_graphics = TRUE;
5808 g_em->crumbled_bitmap = src_bitmap;
5809 g_em->crumbled_src_x = src_x;
5810 g_em->crumbled_src_y = src_y;
5811 g_em->crumbled_border_size = graphic_info[crumbled].border_size;
5814 if (!g->double_movement && (effective_action == ACTION_FALLING ||
5815 effective_action == ACTION_MOVING ||
5816 effective_action == ACTION_PUSHING))
5819 (effective_action == ACTION_FALLING ? MV_DOWN : direction);
5820 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? 1 : 0);
5821 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? 1 : 0);
5822 int num_steps = (i == Ydrip_s1 ||
5825 i == Ydrip_s2B ? 16 : 8);
5826 int cx = ABS(dx) * (TILEX / num_steps);
5827 int cy = ABS(dy) * (TILEY / num_steps);
5828 int step_frame = (i == Ydrip_s2 ||
5829 i == Ydrip_s2B ? j + 8 : j) + 1;
5830 int step = (is_backside ? step_frame : num_steps - step_frame);
5832 if (is_backside) /* tile where movement starts */
5834 if (dx < 0 || dy < 0)
5836 g_em->src_offset_x = cx * step;
5837 g_em->src_offset_y = cy * step;
5841 g_em->dst_offset_x = cx * step;
5842 g_em->dst_offset_y = cy * step;
5845 else /* tile where movement ends */
5847 if (dx < 0 || dy < 0)
5849 g_em->dst_offset_x = cx * step;
5850 g_em->dst_offset_y = cy * step;
5854 g_em->src_offset_x = cx * step;
5855 g_em->src_offset_y = cy * step;
5859 g_em->width = TILEX - cx * step;
5860 g_em->height = TILEY - cy * step;
5863 /* create unique graphic identifier to decide if tile must be redrawn */
5864 /* bit 31 - 16 (16 bit): EM style element
5865 bit 15 - 12 ( 4 bit): EM style frame
5866 bit 11 - 6 ( 6 bit): graphic width
5867 bit 5 - 0 ( 6 bit): graphic height */
5868 g_em->unique_identifier =
5869 (i << 16) | (j << 12) | (g_em->width << 6) | g_em->height;
5872 if (g_em->bitmap != debug_bitmap ||
5873 g_em->src_x != debug_src_x ||
5874 g_em->src_y != debug_src_y ||
5875 g_em->src_offset_x != 0 ||
5876 g_em->src_offset_y != 0 ||
5877 g_em->dst_offset_x != 0 ||
5878 g_em->dst_offset_y != 0 ||
5879 g_em->width != TILEX ||
5880 g_em->height != TILEY)
5882 static int last_i = -1;
5890 printf("::: EMC GFX ERROR for element %d -> %d ('%s', '%s', %d)",
5891 i, element, element_info[element].token_name,
5892 element_action_info[effective_action].suffix, direction);
5894 if (element != effective_element)
5895 printf(" [%d ('%s')]",
5897 element_info[effective_element].token_name);
5901 if (g_em->bitmap != debug_bitmap)
5902 printf(" %d (%d): different bitmap! (0x%08x != 0x%08x)\n",
5903 j, is_backside, (int)(g_em->bitmap), (int)(debug_bitmap));
5905 if (g_em->src_x != debug_src_x ||
5906 g_em->src_y != debug_src_y)
5907 printf(" frame %d (%c): %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
5908 j, (is_backside ? 'B' : 'F'),
5909 g_em->src_x, g_em->src_y,
5910 g_em->src_x / 32, g_em->src_y / 32,
5911 debug_src_x, debug_src_y,
5912 debug_src_x / 32, debug_src_y / 32);
5914 if (g_em->src_offset_x != 0 ||
5915 g_em->src_offset_y != 0 ||
5916 g_em->dst_offset_x != 0 ||
5917 g_em->dst_offset_y != 0)
5918 printf(" %d (%d): offsets %d,%d and %d,%d should be all 0\n",
5920 g_em->src_offset_x, g_em->src_offset_y,
5921 g_em->dst_offset_x, g_em->dst_offset_y);
5923 if (g_em->width != TILEX ||
5924 g_em->height != TILEY)
5925 printf(" %d (%d): size %d,%d should be %d,%d\n",
5927 g_em->width, g_em->height, TILEX, TILEY);
5934 for (i = 0; i < TILE_MAX; i++)
5936 for (j = 0; j < 8; j++)
5938 int element = object_mapping[i].element_rnd;
5939 int action = object_mapping[i].action;
5941 if (action == ACTION_SMASHED_BY_ROCK &&
5942 element_info[element].graphic[action] ==
5943 element_info[element].graphic[ACTION_DEFAULT])
5945 /* no separate animation for "smashed by rock" -- use rock instead */
5946 struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
5947 struct GraphicInfo_EM *g_xx = &graphic_info_em_object[Ystone_s][7 - j];
5949 g_em->bitmap = g_xx->bitmap;
5950 g_em->src_x = g_xx->src_x;
5951 g_em->src_y = g_xx->src_y;
5952 g_em->src_offset_x = g_xx->src_offset_x;
5953 g_em->src_offset_y = g_xx->src_offset_y;
5954 g_em->dst_offset_x = g_xx->dst_offset_x;
5955 g_em->dst_offset_y = g_xx->dst_offset_y;
5956 g_em->width = g_xx->width;
5957 g_em->height = g_xx->height;
5959 g_em->preserve_background = TRUE;
5964 for (p = 0; p < 2; p++)
5966 for (i = 0; i < SPR_MAX; i++)
5968 int element = player_mapping[p][i].element_rnd;
5969 int action = player_mapping[p][i].action;
5970 int direction = player_mapping[p][i].direction;
5972 for (j = 0; j < 8; j++)
5974 int effective_element = element;
5975 int effective_action = action;
5976 int graphic = (direction == MV_NO_MOVING ?
5977 el_act2img(effective_element, effective_action) :
5978 el_act_dir2img(effective_element, effective_action,
5980 struct GraphicInfo *g = &graphic_info[graphic];
5981 struct GraphicInfo_EM *g_em = &graphic_info_em_player[p][i][7 - j];
5987 Bitmap *debug_bitmap = g_em->bitmap;
5988 int debug_src_x = g_em->src_x;
5989 int debug_src_y = g_em->src_y;
5992 int frame = getAnimationFrame(g->anim_frames,
5995 g->anim_start_frame,
5998 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x,&src_y, FALSE);
6000 g_em->bitmap = src_bitmap;
6001 g_em->src_x = src_x;
6002 g_em->src_y = src_y;
6003 g_em->src_offset_x = 0;
6004 g_em->src_offset_y = 0;
6005 g_em->dst_offset_x = 0;
6006 g_em->dst_offset_y = 0;
6007 g_em->width = TILEX;
6008 g_em->height = TILEY;
6011 if (g_em->bitmap != debug_bitmap ||
6012 g_em->src_x != debug_src_x ||
6013 g_em->src_y != debug_src_y)
6015 static int last_i = -1;
6023 printf("::: EMC GFX ERROR for p/a %d/%d -> %d ('%s', '%s', %d)",
6024 p, i, element, element_info[element].token_name,
6025 element_action_info[effective_action].suffix, direction);
6027 if (element != effective_element)
6028 printf(" [%d ('%s')]",
6030 element_info[effective_element].token_name);
6034 if (g_em->bitmap != debug_bitmap)
6035 printf(" %d: different bitmap! (0x%08x != 0x%08x)\n",
6036 j, (int)(g_em->bitmap), (int)(debug_bitmap));
6038 if (g_em->src_x != debug_src_x ||
6039 g_em->src_y != debug_src_y)
6040 printf(" frame %d: %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
6042 g_em->src_x, g_em->src_y,
6043 g_em->src_x / 32, g_em->src_y / 32,
6044 debug_src_x, debug_src_y,
6045 debug_src_x / 32, debug_src_y / 32);