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)
286 if ((redraw_mask & REDRAW_DOOR_2) == REDRAW_DOOR_2)
288 BlitBitmap(backbuffer, window, VX, VY, VXSIZE, VYSIZE, VX, VY);
292 if (redraw_mask & REDRAW_VIDEO_1)
293 BlitBitmap(backbuffer, window,
294 VX + VIDEO_DISPLAY1_XPOS, VY + VIDEO_DISPLAY1_YPOS,
295 VIDEO_DISPLAY_XSIZE, VIDEO_DISPLAY_YSIZE,
296 VX + VIDEO_DISPLAY1_XPOS, VY + VIDEO_DISPLAY1_YPOS);
297 if (redraw_mask & REDRAW_VIDEO_2)
298 BlitBitmap(backbuffer, window,
299 VX + VIDEO_DISPLAY2_XPOS, VY + VIDEO_DISPLAY2_YPOS,
300 VIDEO_DISPLAY_XSIZE, VIDEO_DISPLAY_YSIZE,
301 VX + VIDEO_DISPLAY2_XPOS, VY + VIDEO_DISPLAY2_YPOS);
302 if (redraw_mask & REDRAW_VIDEO_3)
303 BlitBitmap(backbuffer, window,
304 VX + VIDEO_CONTROL_XPOS, VY + VIDEO_CONTROL_YPOS,
305 VIDEO_CONTROL_XSIZE, VIDEO_CONTROL_YSIZE,
306 VX + VIDEO_CONTROL_XPOS, VY + VIDEO_CONTROL_YPOS);
311 if (redraw_mask & REDRAW_DOOR_3)
312 BlitBitmap(backbuffer, window, EX, EY, EXSIZE, EYSIZE, EX, EY);
314 redraw_mask &= ~REDRAW_DOORS;
317 if (redraw_mask & REDRAW_MICROLEVEL)
319 BlitBitmap(backbuffer, window, SX, SY + 10 * TILEY, SXSIZE, 7 * TILEY,
320 SX, SY + 10 * TILEY);
322 redraw_mask &= ~REDRAW_MICROLEVEL;
325 if (redraw_mask & REDRAW_TILES)
327 for (x = 0; x < SCR_FIELDX; x++)
328 for (y = 0 ; y < SCR_FIELDY; y++)
329 if (redraw[redraw_x1 + x][redraw_y1 + y])
330 BlitBitmap(buffer, window,
331 FX + x * TILEX, FY + y * TILEY, TILEX, TILEY,
332 SX + x * TILEX, SY + y * TILEY);
335 if (redraw_mask & REDRAW_FPS) /* display frames per second */
340 sprintf(info1, " (only every %d. frame)", global.fps_slowdown_factor);
341 if (!global.fps_slowdown)
344 sprintf(text, "%.1f fps%s", global.frames_per_second, info1);
345 DrawTextExt(window, SX, SY, text, FONT_TEXT_2, BLIT_OPAQUE);
350 for (x = 0; x < MAX_BUF_XSIZE; x++)
351 for (y = 0; y < MAX_BUF_YSIZE; y++)
354 redraw_mask = REDRAW_NONE;
360 long fading_delay = 300;
362 if (setup.fading && (redraw_mask & REDRAW_FIELD))
369 ClearRectangle(window, REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
372 for (i = 0; i < 2 * FULL_SYSIZE; i++)
374 for (y = 0; y < FULL_SYSIZE; y++)
376 BlitBitmap(backbuffer, window,
377 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
385 for (i = 1; i < FULL_SYSIZE; i+=2)
386 BlitBitmap(backbuffer, window,
387 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
393 SetClipOrigin(clip_gc[PIX_FADEMASK], 0, 0);
394 BlitBitmapMasked(backbuffer, window,
395 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
400 SetClipOrigin(clip_gc[PIX_FADEMASK], -1, -1);
401 BlitBitmapMasked(backbuffer, window,
402 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
407 SetClipOrigin(clip_gc[PIX_FADEMASK], 0, -1);
408 BlitBitmapMasked(backbuffer, window,
409 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
414 SetClipOrigin(clip_gc[PIX_FADEMASK], -1, 0);
415 BlitBitmapMasked(backbuffer, window,
416 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
421 redraw_mask &= ~REDRAW_MAIN;
428 void SetMainBackgroundImageIfDefined(int graphic)
430 if (graphic_info[graphic].bitmap)
431 SetMainBackgroundImage(graphic);
434 void SetMainBackgroundImage(int graphic)
436 SetMainBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
437 graphic_info[graphic].bitmap ?
438 graphic_info[graphic].bitmap :
439 graphic_info[IMG_BACKGROUND].bitmap);
442 void SetDoorBackgroundImage(int graphic)
444 SetDoorBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
445 graphic_info[graphic].bitmap ?
446 graphic_info[graphic].bitmap :
447 graphic_info[IMG_BACKGROUND].bitmap);
450 void DrawBackground(int dst_x, int dst_y, int width, int height)
452 ClearRectangleOnBackground(backbuffer, dst_x, dst_y, width, height);
454 redraw_mask |= REDRAW_FIELD;
459 DrawBackground(REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
461 if (setup.soft_scrolling && game_status == GAME_MODE_PLAYING)
463 ClearRectangle(fieldbuffer, 0, 0, FXSIZE, FYSIZE);
464 SetDrawtoField(DRAW_BUFFERED);
467 SetDrawtoField(DRAW_BACKBUFFER);
469 if (setup.direct_draw && game_status == GAME_MODE_PLAYING)
471 ClearRectangle(window, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
472 SetDrawtoField(DRAW_DIRECT);
476 void MarkTileDirty(int x, int y)
478 int xx = redraw_x1 + x;
479 int yy = redraw_y1 + y;
484 redraw[xx][yy] = TRUE;
485 redraw_mask |= REDRAW_TILES;
488 void SetBorderElement()
492 BorderElement = EL_EMPTY;
494 for (y = 0; y < lev_fieldy && BorderElement == EL_EMPTY; y++)
496 for (x = 0; x < lev_fieldx; x++)
498 if (!IS_INDESTRUCTIBLE(Feld[x][y]))
499 BorderElement = EL_STEELWALL;
501 if (y != 0 && y != lev_fieldy - 1 && x != lev_fieldx - 1)
507 void SetRandomAnimationValue(int x, int y)
509 gfx.anim_random_frame = GfxRandom[x][y];
512 inline int getGraphicAnimationFrame(int graphic, int sync_frame)
514 /* animation synchronized with global frame counter, not move position */
515 if (graphic_info[graphic].anim_global_sync || sync_frame < 0)
516 sync_frame = FrameCounter;
518 return getAnimationFrame(graphic_info[graphic].anim_frames,
519 graphic_info[graphic].anim_delay,
520 graphic_info[graphic].anim_mode,
521 graphic_info[graphic].anim_start_frame,
525 inline void getGraphicSourceExt(int graphic, int frame, Bitmap **bitmap,
526 int *x, int *y, boolean get_backside)
528 struct GraphicInfo *g = &graphic_info[graphic];
529 int src_x = g->src_x + (get_backside ? g->offset2_x : 0);
530 int src_y = g->src_y + (get_backside ? g->offset2_y : 0);
534 if (g->offset_y == 0) /* frames are ordered horizontally */
536 int max_width = g->anim_frames_per_line * g->width;
538 int pos = (src_y / g->height) * max_width + src_x + frame * g->offset_x;
540 *x = pos % max_width;
541 *y = src_y % g->height + pos / max_width * g->height;
543 *x = (src_x + frame * g->offset_x) % max_width;
544 *y = src_y + (src_x + frame * g->offset_x) / max_width * g->height;
547 else if (g->offset_x == 0) /* frames are ordered vertically */
549 int max_height = g->anim_frames_per_line * g->height;
551 int pos = (src_x / g->width) * max_height + src_y + frame * g->offset_y;
553 *x = src_x % g->width + pos / max_height * g->width;
554 *y = pos % max_height;
556 *x = src_x + (src_y + frame * g->offset_y) / max_height * g->width;
557 *y = (src_y + frame * g->offset_y) % max_height;
560 else /* frames are ordered diagonally */
562 *x = src_x + frame * g->offset_x;
563 *y = src_y + frame * g->offset_y;
567 void getGraphicSource(int graphic, int frame, Bitmap **bitmap, int *x, int *y)
569 getGraphicSourceExt(graphic, frame, bitmap, x, y, FALSE);
572 void DrawGraphic(int x, int y, int graphic, int frame)
575 if (!IN_SCR_FIELD(x, y))
577 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
578 printf("DrawGraphic(): This should never happen!\n");
583 DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic, frame);
587 void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
593 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
594 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
597 void DrawGraphicThruMask(int x, int y, int graphic, int frame)
600 if (!IN_SCR_FIELD(x, y))
602 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
603 printf("DrawGraphicThruMask(): This should never happen!\n");
608 DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY, graphic,
613 void DrawGraphicThruMaskExt(DrawBuffer *d, int dst_x, int dst_y, int graphic,
619 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
621 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
622 dst_x - src_x, dst_y - src_y);
623 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dst_x, dst_y);
626 void DrawMiniGraphic(int x, int y, int graphic)
628 DrawMiniGraphicExt(drawto, SX + x * MINI_TILEX,SY + y * MINI_TILEY, graphic);
629 MarkTileDirty(x / 2, y / 2);
632 void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
634 struct GraphicInfo *g = &graphic_info[graphic];
636 int mini_starty = g->bitmap->height * 2 / 3;
639 *x = mini_startx + g->src_x / 2;
640 *y = mini_starty + g->src_y / 2;
643 void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
648 getMiniGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
649 BlitBitmap(src_bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
652 inline static void DrawGraphicShiftedNormal(int x, int y, int dx, int dy,
653 int graphic, int frame,
654 int cut_mode, int mask_mode)
659 int width = TILEX, height = TILEY;
662 if (dx || dy) /* shifted graphic */
664 if (x < BX1) /* object enters playfield from the left */
671 else if (x > BX2) /* object enters playfield from the right */
677 else if (x==BX1 && dx < 0) /* object leaves playfield to the left */
683 else if (x==BX2 && dx > 0) /* object leaves playfield to the right */
685 else if (dx) /* general horizontal movement */
686 MarkTileDirty(x + SIGN(dx), y);
688 if (y < BY1) /* object enters playfield from the top */
690 if (cut_mode==CUT_BELOW) /* object completely above top border */
698 else if (y > BY2) /* object enters playfield from the bottom */
704 else if (y==BY1 && dy < 0) /* object leaves playfield to the top */
710 else if (dy > 0 && cut_mode == CUT_ABOVE)
712 if (y == BY2) /* object completely above bottom border */
718 MarkTileDirty(x, y + 1);
719 } /* object leaves playfield to the bottom */
720 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
722 else if (dy) /* general vertical movement */
723 MarkTileDirty(x, y + SIGN(dy));
727 if (!IN_SCR_FIELD(x, y))
729 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
730 printf("DrawGraphicShifted(): This should never happen!\n");
735 if (width > 0 && height > 0)
737 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
742 dst_x = FX + x * TILEX + dx;
743 dst_y = FY + y * TILEY + dy;
745 if (mask_mode == USE_MASKING)
747 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
748 dst_x - src_x, dst_y - src_y);
749 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
753 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
760 inline static void DrawGraphicShiftedDouble(int x, int y, int dx, int dy,
761 int graphic, int frame,
762 int cut_mode, int mask_mode)
767 int width = TILEX, height = TILEY;
770 int x2 = x + SIGN(dx);
771 int y2 = y + SIGN(dy);
772 int anim_frames = graphic_info[graphic].anim_frames;
773 int sync_frame = (dx ? ABS(dx) : ABS(dy)) * anim_frames / TILESIZE;
775 /* re-calculate animation frame for two-tile movement animation */
776 frame = getGraphicAnimationFrame(graphic, sync_frame);
778 if (IN_SCR_FIELD(x1, y1)) /* movement start graphic inside screen area */
780 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, TRUE);
782 dst_x = FX + x1 * TILEX;
783 dst_y = FY + y1 * TILEY;
785 if (mask_mode == USE_MASKING)
787 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
788 dst_x - src_x, dst_y - src_y);
789 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
793 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
796 MarkTileDirty(x1, y1);
799 if (IN_SCR_FIELD(x2, y2)) /* movement end graphic inside screen area */
801 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, FALSE);
803 dst_x = FX + x2 * TILEX;
804 dst_y = FY + y2 * TILEY;
806 if (mask_mode == USE_MASKING)
808 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
809 dst_x - src_x, dst_y - src_y);
810 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
814 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
817 MarkTileDirty(x2, y2);
821 printf("::: DONE DrawGraphicShiftedDouble");
827 static void DrawGraphicShifted(int x, int y, int dx, int dy,
828 int graphic, int frame,
829 int cut_mode, int mask_mode)
833 DrawGraphic(x, y, graphic, frame);
838 if (graphic_info[graphic].double_movement) /* EM style movement images */
839 DrawGraphicShiftedDouble(x, y, dx, dy, graphic, frame, cut_mode,mask_mode);
841 DrawGraphicShiftedNormal(x, y, dx, dy, graphic, frame, cut_mode,mask_mode);
844 void DrawGraphicShiftedThruMask(int x, int y, int dx, int dy, int graphic,
845 int frame, int cut_mode)
847 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, USE_MASKING);
850 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
851 int cut_mode, int mask_mode)
853 int lx = LEVELX(x), ly = LEVELY(y);
857 if (IN_LEV_FIELD(lx, ly))
859 SetRandomAnimationValue(lx, ly);
861 graphic = el_act_dir2img(element, GfxAction[lx][ly], GfxDir[lx][ly]);
862 frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
864 /* do not use double (EM style) movement graphic when not moving */
865 if (graphic_info[graphic].double_movement && !dx && !dy)
867 graphic = el_act_dir2img(element, ACTION_DEFAULT, GfxDir[lx][ly]);
868 frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
871 else /* border element */
873 graphic = el2img(element);
874 frame = getGraphicAnimationFrame(graphic, -1);
877 if (element == EL_EXPANDABLE_WALL)
879 boolean left_stopped = FALSE, right_stopped = FALSE;
881 if (!IN_LEV_FIELD(lx - 1, ly) || IS_WALL(Feld[lx - 1][ly]))
883 if (!IN_LEV_FIELD(lx + 1, ly) || IS_WALL(Feld[lx + 1][ly]))
884 right_stopped = TRUE;
886 if (left_stopped && right_stopped)
888 else if (left_stopped)
890 graphic = IMG_EXPANDABLE_WALL_GROWING_RIGHT;
891 frame = graphic_info[graphic].anim_frames - 1;
893 else if (right_stopped)
895 graphic = IMG_EXPANDABLE_WALL_GROWING_LEFT;
896 frame = graphic_info[graphic].anim_frames - 1;
901 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
902 else if (mask_mode == USE_MASKING)
903 DrawGraphicThruMask(x, y, graphic, frame);
905 DrawGraphic(x, y, graphic, frame);
908 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
909 int cut_mode, int mask_mode)
911 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
912 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
913 cut_mode, mask_mode);
916 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
919 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
922 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
925 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
928 void DrawLevelElementThruMask(int x, int y, int element)
930 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
933 void DrawLevelFieldThruMask(int x, int y)
935 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
938 #define TILE_GFX_ELEMENT(x, y) \
939 (GfxElement[x][y] != EL_UNDEFINED && Feld[x][y] != EL_EXPLOSION ? \
940 GfxElement[x][y] : Feld[x][y])
942 static void DrawLevelFieldCrumbledSandExt(int x, int y, int graphic, int frame)
946 int sx = SCREENX(x), sy = SCREENY(y);
948 int width, height, cx, cy, i;
950 int crumbled_border_size = graphic_info[graphic].border_size;
952 int snip = TILEX / 8; /* number of border pixels from "crumbled graphic" */
954 static int xy[4][2] =
963 if (x == 0 && y == 7)
964 printf("::: %d, %d [%d]\n", GfxElement[x][y], Feld[x][y],
965 crumbled_border_size);
968 if (!IN_LEV_FIELD(x, y))
971 element = TILE_GFX_ELEMENT(x, y);
973 /* crumble field itself */
974 if (GFX_CRUMBLED(element) && !IS_MOVING(x, y))
976 if (!IN_SCR_FIELD(sx, sy))
979 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
981 for (i = 0; i < 4; i++)
983 int xx = x + xy[i][0];
984 int yy = y + xy[i][1];
987 element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
990 element = (IN_LEV_FIELD(xx, yy) ? Feld[xx][yy] : BorderElement);
993 /* check if neighbour field is of same type */
994 if (GFX_CRUMBLED(element) && !IS_MOVING(xx, yy))
998 if (Feld[x][y] == EL_CUSTOM_START + 123)
999 printf("::: crumble [%d] THE CHAOS ENGINE (%d, %d): %d, %d\n",
1000 i, Feld[x][y], element,
1001 GFX_CRUMBLED(element), IS_MOVING(x, y));
1004 if (i == 1 || i == 2)
1006 width = crumbled_border_size;
1008 cx = (i == 2 ? TILEX - crumbled_border_size : 0);
1014 height = crumbled_border_size;
1016 cy = (i == 3 ? TILEY - crumbled_border_size : 0);
1019 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1020 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
1023 MarkTileDirty(sx, sy);
1025 else /* crumble neighbour fields */
1028 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1031 for (i = 0; i < 4; i++)
1033 int xx = x + xy[i][0];
1034 int yy = y + xy[i][1];
1035 int sxx = sx + xy[i][0];
1036 int syy = sy + xy[i][1];
1039 if (!IN_LEV_FIELD(xx, yy) ||
1040 !IN_SCR_FIELD(sxx, syy) ||
1044 element = TILE_GFX_ELEMENT(xx, yy);
1046 if (!GFX_CRUMBLED(element))
1049 if (!IN_LEV_FIELD(xx, yy) ||
1050 !IN_SCR_FIELD(sxx, syy) ||
1051 !GFX_CRUMBLED(Feld[xx][yy]) ||
1057 graphic = el_act2crm(Feld[xx][yy], ACTION_DEFAULT);
1058 crumbled_border_size = graphic_info[graphic].border_size;
1060 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1063 if (i == 1 || i == 2)
1065 width = crumbled_border_size;
1067 cx = (i == 1 ? TILEX - crumbled_border_size : 0);
1073 height = crumbled_border_size;
1075 cy = (i == 0 ? TILEY - crumbled_border_size : 0);
1078 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1079 width, height, FX + sxx * TILEX + cx, FY + syy * TILEY + cy);
1081 MarkTileDirty(sxx, syy);
1086 void DrawLevelFieldCrumbledSand(int x, int y)
1091 if (!IN_LEV_FIELD(x, y))
1094 graphic = el_act2crm(Feld[x][y], ACTION_DEFAULT);
1096 DrawLevelFieldCrumbledSandExt(x, y, graphic, 0);
1098 DrawLevelFieldCrumbledSandExt(x, y, IMG_SAND_CRUMBLED, 0);
1102 void DrawLevelFieldCrumbledSandDigging(int x, int y, int direction,
1106 int graphic1 = el_act_dir2img(GfxElement[x][y], ACTION_DIGGING, direction);
1107 int graphic2 = el_act_dir2crm(GfxElement[x][y], ACTION_DIGGING, direction);
1109 int graphic1 = el_act_dir2img(EL_SAND, ACTION_DIGGING, direction);
1110 int graphic2 = el_act_dir2img(EL_SAND_CRUMBLED, ACTION_DIGGING, direction);
1112 int frame1 = getGraphicAnimationFrame(graphic1, step_frame);
1113 int frame2 = getGraphicAnimationFrame(graphic2, step_frame);
1114 int sx = SCREENX(x), sy = SCREENY(y);
1116 DrawGraphic(sx, sy, graphic1, frame1);
1117 DrawLevelFieldCrumbledSandExt(x, y, graphic2, frame2);
1120 void DrawLevelFieldCrumbledSandNeighbours(int x, int y)
1122 int sx = SCREENX(x), sy = SCREENY(y);
1123 static int xy[4][2] =
1132 for (i = 0; i < 4; i++)
1134 int xx = x + xy[i][0];
1135 int yy = y + xy[i][1];
1136 int sxx = sx + xy[i][0];
1137 int syy = sy + xy[i][1];
1139 if (!IN_LEV_FIELD(xx, yy) ||
1140 !IN_SCR_FIELD(sxx, syy) ||
1141 !GFX_CRUMBLED(Feld[xx][yy]) ||
1145 DrawLevelField(xx, yy);
1149 static int getBorderElement(int x, int y)
1153 { EL_STEELWALL_TOPLEFT, EL_INVISIBLE_STEELWALL_TOPLEFT },
1154 { EL_STEELWALL_TOPRIGHT, EL_INVISIBLE_STEELWALL_TOPRIGHT },
1155 { EL_STEELWALL_BOTTOMLEFT, EL_INVISIBLE_STEELWALL_BOTTOMLEFT },
1156 { EL_STEELWALL_BOTTOMRIGHT, EL_INVISIBLE_STEELWALL_BOTTOMRIGHT },
1157 { EL_STEELWALL_VERTICAL, EL_INVISIBLE_STEELWALL_VERTICAL },
1158 { EL_STEELWALL_HORIZONTAL, EL_INVISIBLE_STEELWALL_HORIZONTAL },
1159 { EL_STEELWALL, EL_INVISIBLE_STEELWALL }
1161 int steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
1162 int steel_position = (x == -1 && y == -1 ? 0 :
1163 x == lev_fieldx && y == -1 ? 1 :
1164 x == -1 && y == lev_fieldy ? 2 :
1165 x == lev_fieldx && y == lev_fieldy ? 3 :
1166 x == -1 || x == lev_fieldx ? 4 :
1167 y == -1 || y == lev_fieldy ? 5 : 6);
1169 return border[steel_position][steel_type];
1172 void DrawScreenElement(int x, int y, int element)
1174 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1175 DrawLevelFieldCrumbledSand(LEVELX(x), LEVELY(y));
1178 void DrawLevelElement(int x, int y, int element)
1180 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1181 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1184 void DrawScreenField(int x, int y)
1186 int lx = LEVELX(x), ly = LEVELY(y);
1187 int element, content;
1189 if (!IN_LEV_FIELD(lx, ly))
1191 if (lx < -1 || lx > lev_fieldx || ly < -1 || ly > lev_fieldy)
1194 element = getBorderElement(lx, ly);
1196 DrawScreenElement(x, y, element);
1200 element = Feld[lx][ly];
1201 content = Store[lx][ly];
1203 if (IS_MOVING(lx, ly))
1205 int horiz_move = (MovDir[lx][ly] == MV_LEFT || MovDir[lx][ly] == MV_RIGHT);
1206 boolean cut_mode = NO_CUTTING;
1208 if (element == EL_QUICKSAND_EMPTYING ||
1209 element == EL_MAGIC_WALL_EMPTYING ||
1210 element == EL_BD_MAGIC_WALL_EMPTYING ||
1211 element == EL_AMOEBA_DROPPING)
1212 cut_mode = CUT_ABOVE;
1213 else if (element == EL_QUICKSAND_FILLING ||
1214 element == EL_MAGIC_WALL_FILLING ||
1215 element == EL_BD_MAGIC_WALL_FILLING)
1216 cut_mode = CUT_BELOW;
1218 if (cut_mode == CUT_ABOVE)
1219 DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1221 DrawScreenElement(x, y, EL_EMPTY);
1224 DrawScreenElementShifted(x, y, MovPos[lx][ly], 0, element, NO_CUTTING);
1225 else if (cut_mode == NO_CUTTING)
1226 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], element, cut_mode);
1228 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], content, cut_mode);
1230 if (content == EL_ACID)
1232 int dir = MovDir[lx][ly];
1233 int newlx = lx + (dir == MV_LEFT ? -1 : dir == MV_RIGHT ? +1 : 0);
1234 int newly = ly + (dir == MV_UP ? -1 : dir == MV_DOWN ? +1 : 0);
1236 DrawLevelElementThruMask(newlx, newly, EL_ACID);
1239 else if (IS_BLOCKED(lx, ly))
1244 boolean cut_mode = NO_CUTTING;
1245 int element_old, content_old;
1247 Blocked2Moving(lx, ly, &oldx, &oldy);
1250 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1251 MovDir[oldx][oldy] == MV_RIGHT);
1253 element_old = Feld[oldx][oldy];
1254 content_old = Store[oldx][oldy];
1256 if (element_old == EL_QUICKSAND_EMPTYING ||
1257 element_old == EL_MAGIC_WALL_EMPTYING ||
1258 element_old == EL_BD_MAGIC_WALL_EMPTYING ||
1259 element_old == EL_AMOEBA_DROPPING)
1260 cut_mode = CUT_ABOVE;
1262 DrawScreenElement(x, y, EL_EMPTY);
1265 DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
1267 else if (cut_mode == NO_CUTTING)
1268 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
1271 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
1274 else if (IS_DRAWABLE(element))
1275 DrawScreenElement(x, y, element);
1277 DrawScreenElement(x, y, EL_EMPTY);
1280 void DrawLevelField(int x, int y)
1282 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1283 DrawScreenField(SCREENX(x), SCREENY(y));
1284 else if (IS_MOVING(x, y))
1288 Moving2Blocked(x, y, &newx, &newy);
1289 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1290 DrawScreenField(SCREENX(newx), SCREENY(newy));
1292 else if (IS_BLOCKED(x, y))
1296 Blocked2Moving(x, y, &oldx, &oldy);
1297 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1298 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1302 void DrawMiniElement(int x, int y, int element)
1306 graphic = el2edimg(element);
1307 DrawMiniGraphic(x, y, graphic);
1310 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1312 int x = sx + scroll_x, y = sy + scroll_y;
1314 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1315 DrawMiniElement(sx, sy, EL_EMPTY);
1316 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1317 DrawMiniElement(sx, sy, Feld[x][y]);
1319 DrawMiniGraphic(sx, sy, el2edimg(getBorderElement(x, y)));
1322 void DrawEnvelopeBackground(int envelope_nr, int startx, int starty,
1323 int x, int y, int xsize, int ysize, int font_nr)
1325 int font_width = getFontWidth(font_nr);
1326 int font_height = getFontHeight(font_nr);
1327 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1330 int dst_x = SX + startx + x * font_width;
1331 int dst_y = SY + starty + y * font_height;
1332 int width = graphic_info[graphic].width;
1333 int height = graphic_info[graphic].height;
1334 int inner_width = MAX(width - 2 * font_width, font_width);
1335 int inner_height = MAX(height - 2 * font_height, font_height);
1336 int inner_sx = (width >= 3 * font_width ? font_width : 0);
1337 int inner_sy = (height >= 3 * font_height ? font_height : 0);
1338 boolean draw_masked = graphic_info[graphic].draw_masked;
1340 getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
1342 if (src_bitmap == NULL || width < font_width || height < font_height)
1344 ClearRectangle(drawto, dst_x, dst_y, font_width, font_height);
1348 src_x += (x == 0 ? 0 : x == xsize - 1 ? width - font_width :
1349 inner_sx + (x - 1) * font_width % inner_width);
1350 src_y += (y == 0 ? 0 : y == ysize - 1 ? height - font_height :
1351 inner_sy + (y - 1) * font_height % inner_height);
1355 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1356 dst_x - src_x, dst_y - src_y);
1357 BlitBitmapMasked(src_bitmap, drawto, src_x, src_y, font_width, font_height,
1361 BlitBitmap(src_bitmap, drawto, src_x, src_y, font_width, font_height,
1365 void AnimateEnvelope(int envelope_nr, int anim_mode, int action)
1367 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1369 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
1370 int mask_mode = (src_bitmap != NULL ? BLIT_MASKED : BLIT_ON_BACKGROUND);
1372 boolean draw_masked = graphic_info[graphic].draw_masked;
1373 int mask_mode = (draw_masked ? BLIT_MASKED : BLIT_ON_BACKGROUND);
1375 boolean ffwd_delay = (tape.playing && tape.fast_forward);
1376 boolean no_delay = (tape.warp_forward);
1377 unsigned long anim_delay = 0;
1378 int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
1379 int anim_delay_value = (no_delay ? 0 : frame_delay_value);
1380 int font_nr = FONT_ENVELOPE_1 + envelope_nr;
1381 int font_width = getFontWidth(font_nr);
1382 int font_height = getFontHeight(font_nr);
1383 int max_xsize = level.envelope_xsize[envelope_nr];
1384 int max_ysize = level.envelope_ysize[envelope_nr];
1385 int xstart = (anim_mode & ANIM_VERTICAL ? max_xsize : 0);
1386 int ystart = (anim_mode & ANIM_HORIZONTAL ? max_ysize : 0);
1387 int xend = max_xsize;
1388 int yend = (anim_mode != ANIM_DEFAULT ? max_ysize : 0);
1389 int xstep = (xstart < xend ? 1 : 0);
1390 int ystep = (ystart < yend || xstep == 0 ? 1 : 0);
1393 for (x = xstart, y = ystart; x <= xend && y <= yend; x += xstep, y += ystep)
1395 int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2;
1396 int ysize = (action == ACTION_CLOSING ? yend - (y - ystart) : y) + 2;
1397 int sx = (SXSIZE - xsize * font_width) / 2;
1398 int sy = (SYSIZE - ysize * font_height) / 2;
1401 SetDrawtoField(DRAW_BUFFERED);
1403 BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
1405 SetDrawtoField(DRAW_BACKBUFFER);
1407 for (yy = 0; yy < ysize; yy++) for (xx = 0; xx < xsize; xx++)
1408 DrawEnvelopeBackground(envelope_nr, sx,sy, xx,yy, xsize, ysize, font_nr);
1410 DrawTextToTextArea(SX + sx + font_width, SY + sy + font_height,
1411 level.envelope_text[envelope_nr], font_nr, max_xsize,
1412 xsize - 2, ysize - 2, mask_mode);
1414 redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
1417 WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
1421 void ShowEnvelope(int envelope_nr)
1423 int element = EL_ENVELOPE_1 + envelope_nr;
1424 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1425 int sound_opening = element_info[element].sound[ACTION_OPENING];
1426 int sound_closing = element_info[element].sound[ACTION_CLOSING];
1427 boolean ffwd_delay = (tape.playing && tape.fast_forward);
1428 boolean no_delay = (tape.warp_forward);
1429 int normal_delay_value = ONE_SECOND_DELAY / (ffwd_delay ? 2 : 1);
1430 int wait_delay_value = (no_delay ? 0 : normal_delay_value);
1431 int anim_mode = graphic_info[graphic].anim_mode;
1432 int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL:
1433 anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode);
1435 game.envelope_active = TRUE; /* needed for RedrawPlayfield() events */
1437 PlaySoundStereo(sound_opening, SOUND_MIDDLE);
1439 if (anim_mode == ANIM_DEFAULT)
1440 AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_OPENING);
1442 AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_OPENING);
1445 Delay(wait_delay_value);
1447 WaitForEventToContinue();
1449 PlaySoundStereo(sound_closing, SOUND_MIDDLE);
1451 if (anim_mode != ANIM_NONE)
1452 AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_CLOSING);
1454 if (anim_mode == ANIM_DEFAULT)
1455 AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_CLOSING);
1457 game.envelope_active = FALSE;
1459 SetDrawtoField(DRAW_BUFFERED);
1461 redraw_mask |= REDRAW_FIELD;
1465 void getMicroGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1467 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
1468 int mini_startx = src_bitmap->width * 3 / 4;
1469 int mini_starty = src_bitmap->height * 2 / 3;
1470 int src_x = mini_startx + graphic_info[graphic].src_x / 8;
1471 int src_y = mini_starty + graphic_info[graphic].src_y / 8;
1473 *bitmap = src_bitmap;
1478 void DrawMicroElement(int xpos, int ypos, int element)
1482 int graphic = el2preimg(element);
1484 getMicroGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1485 BlitBitmap(src_bitmap, drawto, src_x, src_y, MICRO_TILEX, MICRO_TILEY,
1493 SetDrawBackgroundMask(REDRAW_NONE);
1496 for (x = BX1; x <= BX2; x++)
1497 for (y = BY1; y <= BY2; y++)
1498 DrawScreenField(x, y);
1500 redraw_mask |= REDRAW_FIELD;
1503 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1507 for (x = 0; x < size_x; x++)
1508 for (y = 0; y < size_y; y++)
1509 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1511 redraw_mask |= REDRAW_FIELD;
1514 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1518 DrawBackground(xpos, ypos, MICROLEVEL_XSIZE, MICROLEVEL_YSIZE);
1520 if (lev_fieldx < STD_LEV_FIELDX)
1521 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1522 if (lev_fieldy < STD_LEV_FIELDY)
1523 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1525 xpos += MICRO_TILEX;
1526 ypos += MICRO_TILEY;
1528 for (x = -1; x <= STD_LEV_FIELDX; x++)
1530 for (y = -1; y <= STD_LEV_FIELDY; y++)
1532 int lx = from_x + x, ly = from_y + y;
1534 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1535 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1536 level.field[lx][ly]);
1537 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1
1538 && BorderElement != EL_EMPTY)
1539 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1540 getBorderElement(lx, ly));
1544 redraw_mask |= REDRAW_MICROLEVEL;
1547 #define MICROLABEL_EMPTY 0
1548 #define MICROLABEL_LEVEL_NAME 1
1549 #define MICROLABEL_LEVEL_AUTHOR_HEAD 2
1550 #define MICROLABEL_LEVEL_AUTHOR 3
1551 #define MICROLABEL_IMPORTED_FROM_HEAD 4
1552 #define MICROLABEL_IMPORTED_FROM 5
1553 #define MICROLABEL_IMPORTED_BY_HEAD 6
1554 #define MICROLABEL_IMPORTED_BY 7
1556 static void DrawMicroLevelLabelExt(int mode)
1558 char label_text[MAX_OUTPUT_LINESIZE + 1];
1559 int max_len_label_text;
1560 int font_nr = FONT_TEXT_2;
1563 if (mode == MICROLABEL_LEVEL_AUTHOR_HEAD ||
1564 mode == MICROLABEL_IMPORTED_FROM_HEAD ||
1565 mode == MICROLABEL_IMPORTED_BY_HEAD)
1566 font_nr = FONT_TEXT_3;
1568 max_len_label_text = SXSIZE / getFontWidth(font_nr);
1572 for (i = 0; i < max_len_label_text; i++)
1573 label_text[i] = ' ';
1574 label_text[max_len_label_text] = '\0';
1576 if (strlen(label_text) > 0)
1578 int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
1579 int lypos = MICROLABEL2_YPOS;
1581 DrawText(lxpos, lypos, label_text, font_nr);
1586 DrawBackground(SX, MICROLABEL2_YPOS, SXSIZE, getFontHeight(font_nr));
1591 (mode == MICROLABEL_LEVEL_NAME ? level.name :
1592 mode == MICROLABEL_LEVEL_AUTHOR_HEAD ? "created by" :
1593 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
1594 mode == MICROLABEL_IMPORTED_FROM_HEAD ? "imported from" :
1595 mode == MICROLABEL_IMPORTED_FROM ? leveldir_current->imported_from :
1596 mode == MICROLABEL_IMPORTED_BY_HEAD ? "imported by" :
1597 mode == MICROLABEL_IMPORTED_BY ? leveldir_current->imported_by :""),
1598 max_len_label_text);
1599 label_text[max_len_label_text] = '\0';
1601 if (strlen(label_text) > 0)
1603 int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
1604 int lypos = MICROLABEL2_YPOS;
1606 DrawText(lxpos, lypos, label_text, font_nr);
1609 redraw_mask |= REDRAW_MICROLEVEL;
1612 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1614 static unsigned long scroll_delay = 0;
1615 static unsigned long label_delay = 0;
1616 static int from_x, from_y, scroll_direction;
1617 static int label_state, label_counter;
1618 int last_game_status = game_status; /* save current game status */
1620 /* force PREVIEW font on preview level */
1621 game_status = GAME_MODE_PSEUDO_PREVIEW;
1625 from_x = from_y = 0;
1626 scroll_direction = MV_RIGHT;
1630 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1631 DrawMicroLevelLabelExt(label_state);
1633 /* initialize delay counters */
1634 DelayReached(&scroll_delay, 0);
1635 DelayReached(&label_delay, 0);
1637 if (leveldir_current->name)
1639 char label_text[MAX_OUTPUT_LINESIZE + 1];
1640 int font_nr = FONT_TEXT_1;
1641 int max_len_label_text = SXSIZE / getFontWidth(font_nr);
1644 strncpy(label_text, leveldir_current->name, max_len_label_text);
1645 label_text[max_len_label_text] = '\0';
1647 lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
1648 lypos = SY + MICROLABEL1_YPOS;
1650 DrawText(lxpos, lypos, label_text, font_nr);
1653 game_status = last_game_status; /* restore current game status */
1658 /* scroll micro level, if needed */
1659 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1660 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1662 switch (scroll_direction)
1668 scroll_direction = MV_UP;
1672 if (from_x < lev_fieldx - STD_LEV_FIELDX)
1675 scroll_direction = MV_DOWN;
1682 scroll_direction = MV_RIGHT;
1686 if (from_y < lev_fieldy - STD_LEV_FIELDY)
1689 scroll_direction = MV_LEFT;
1696 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1699 /* !!! THIS ALL SUCKS -- SHOULD BE CLEANLY REWRITTEN !!! */
1700 /* redraw micro level label, if needed */
1701 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1702 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1703 strcmp(level.author, leveldir_current->name) != 0 &&
1704 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1706 int max_label_counter = 23;
1708 if (leveldir_current->imported_from != NULL &&
1709 strlen(leveldir_current->imported_from) > 0)
1710 max_label_counter += 14;
1711 if (leveldir_current->imported_by != NULL &&
1712 strlen(leveldir_current->imported_by) > 0)
1713 max_label_counter += 14;
1715 label_counter = (label_counter + 1) % max_label_counter;
1716 label_state = (label_counter >= 0 && label_counter <= 7 ?
1717 MICROLABEL_LEVEL_NAME :
1718 label_counter >= 9 && label_counter <= 12 ?
1719 MICROLABEL_LEVEL_AUTHOR_HEAD :
1720 label_counter >= 14 && label_counter <= 21 ?
1721 MICROLABEL_LEVEL_AUTHOR :
1722 label_counter >= 23 && label_counter <= 26 ?
1723 MICROLABEL_IMPORTED_FROM_HEAD :
1724 label_counter >= 28 && label_counter <= 35 ?
1725 MICROLABEL_IMPORTED_FROM :
1726 label_counter >= 37 && label_counter <= 40 ?
1727 MICROLABEL_IMPORTED_BY_HEAD :
1728 label_counter >= 42 && label_counter <= 49 ?
1729 MICROLABEL_IMPORTED_BY : MICROLABEL_EMPTY);
1731 if (leveldir_current->imported_from == NULL &&
1732 (label_state == MICROLABEL_IMPORTED_FROM_HEAD ||
1733 label_state == MICROLABEL_IMPORTED_FROM))
1734 label_state = (label_state == MICROLABEL_IMPORTED_FROM_HEAD ?
1735 MICROLABEL_IMPORTED_BY_HEAD : MICROLABEL_IMPORTED_BY);
1737 DrawMicroLevelLabelExt(label_state);
1740 game_status = last_game_status; /* restore current game status */
1743 inline void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
1744 int graphic, int sync_frame, int mask_mode)
1746 int frame = getGraphicAnimationFrame(graphic, sync_frame);
1748 if (mask_mode == USE_MASKING)
1749 DrawGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
1751 DrawGraphicExt(dst_bitmap, x, y, graphic, frame);
1754 inline void DrawGraphicAnimation(int x, int y, int graphic)
1756 int lx = LEVELX(x), ly = LEVELY(y);
1758 if (!IN_SCR_FIELD(x, y))
1761 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
1762 graphic, GfxFrame[lx][ly], NO_MASKING);
1763 MarkTileDirty(x, y);
1766 void DrawLevelGraphicAnimation(int x, int y, int graphic)
1768 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
1771 void DrawLevelElementAnimation(int x, int y, int element)
1774 int graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
1776 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
1778 DrawGraphicAnimation(SCREENX(x), SCREENY(y), el2img(element));
1782 inline void DrawLevelGraphicAnimationIfNeeded(int x, int y, int graphic)
1784 int sx = SCREENX(x), sy = SCREENY(y);
1786 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
1789 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
1792 DrawGraphicAnimation(sx, sy, graphic);
1794 if (GFX_CRUMBLED(Feld[x][y]))
1795 DrawLevelFieldCrumbledSand(x, y);
1798 void DrawLevelElementAnimationIfNeeded(int x, int y, int element)
1800 int sx = SCREENX(x), sy = SCREENY(y);
1803 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
1806 graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
1808 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
1811 DrawGraphicAnimation(sx, sy, graphic);
1813 if (GFX_CRUMBLED(element))
1814 DrawLevelFieldCrumbledSand(x, y);
1817 static int getPlayerGraphic(struct PlayerInfo *player, int move_dir)
1819 if (player->use_murphy_graphic)
1821 /* this works only because currently only one player can be "murphy" ... */
1822 static int last_horizontal_dir = MV_LEFT;
1823 int graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, move_dir);
1825 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
1826 last_horizontal_dir = move_dir;
1828 if (graphic == IMG_SP_MURPHY) /* undefined => use special graphic */
1830 int direction = (player->is_snapping ? move_dir : last_horizontal_dir);
1832 graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, direction);
1838 return el_act_dir2img(player->element_nr, player->GfxAction, move_dir);
1841 static boolean equalGraphics(int graphic1, int graphic2)
1843 struct GraphicInfo *g1 = &graphic_info[graphic1];
1844 struct GraphicInfo *g2 = &graphic_info[graphic2];
1846 return (g1->bitmap == g2->bitmap &&
1847 g1->src_x == g2->src_x &&
1848 g1->src_y == g2->src_y &&
1849 g1->anim_frames == g2->anim_frames &&
1850 g1->anim_delay == g2->anim_delay &&
1851 g1->anim_mode == g2->anim_mode);
1854 void DrawAllPlayers()
1858 for (i = 0; i < MAX_PLAYERS; i++)
1859 if (stored_player[i].active)
1860 DrawPlayer(&stored_player[i]);
1863 void DrawPlayerField(int x, int y)
1865 if (!IS_PLAYER(x, y))
1868 DrawPlayer(PLAYERINFO(x, y));
1871 void DrawPlayer(struct PlayerInfo *player)
1873 int jx = player->jx;
1874 int jy = player->jy;
1875 int move_dir = player->MovDir;
1877 int last_jx = player->last_jx;
1878 int last_jy = player->last_jy;
1879 int next_jx = jx + (jx - last_jx);
1880 int next_jy = jy + (jy - last_jy);
1881 boolean player_is_moving = (last_jx != jx || last_jy != jy ? TRUE : FALSE);
1883 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? +1 : 0);
1884 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? +1 : 0);
1885 int last_jx = (player->is_moving ? jx - dx : jx);
1886 int last_jy = (player->is_moving ? jy - dy : jy);
1887 int next_jx = jx + dx;
1888 int next_jy = jy + dy;
1889 boolean player_is_moving = (player->MovPos ? TRUE : FALSE);
1891 int sx = SCREENX(jx), sy = SCREENY(jy);
1892 int sxx = 0, syy = 0;
1893 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
1895 int action = ACTION_DEFAULT;
1896 int last_player_graphic = getPlayerGraphic(player, move_dir);
1897 int last_player_frame = player->Frame;
1900 if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
1904 if (!IN_LEV_FIELD(jx, jy))
1906 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
1907 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
1908 printf("DrawPlayerField(): This should never happen!\n");
1913 if (element == EL_EXPLOSION)
1916 action = (player->is_pushing ? ACTION_PUSHING :
1917 player->is_digging ? ACTION_DIGGING :
1918 player->is_collecting ? ACTION_COLLECTING :
1919 player->is_moving ? ACTION_MOVING :
1920 player->is_snapping ? ACTION_SNAPPING :
1921 player->is_dropping ? ACTION_DROPPING :
1922 player->is_waiting ? player->action_waiting : ACTION_DEFAULT);
1924 InitPlayerGfxAnimation(player, action, move_dir);
1926 /* ----------------------------------------------------------------------- */
1927 /* draw things in the field the player is leaving, if needed */
1928 /* ----------------------------------------------------------------------- */
1931 if (player->is_moving)
1933 if (player_is_moving)
1936 if (Back[last_jx][last_jy] && IS_DRAWABLE(last_element))
1938 DrawLevelElement(last_jx, last_jy, Back[last_jx][last_jy]);
1940 if (last_element == EL_DYNAMITE_ACTIVE ||
1941 last_element == EL_SP_DISK_RED_ACTIVE)
1942 DrawDynamite(last_jx, last_jy);
1944 DrawLevelFieldThruMask(last_jx, last_jy);
1946 else if (last_element == EL_DYNAMITE_ACTIVE ||
1947 last_element == EL_SP_DISK_RED_ACTIVE)
1948 DrawDynamite(last_jx, last_jy);
1950 DrawLevelField(last_jx, last_jy);
1952 if (player->is_pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
1953 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
1956 if (!IN_SCR_FIELD(sx, sy))
1959 if (setup.direct_draw)
1960 SetDrawtoField(DRAW_BUFFERED);
1962 /* ----------------------------------------------------------------------- */
1963 /* draw things behind the player, if needed */
1964 /* ----------------------------------------------------------------------- */
1967 DrawLevelElement(jx, jy, Back[jx][jy]);
1968 else if (IS_ACTIVE_BOMB(element))
1969 DrawLevelElement(jx, jy, EL_EMPTY);
1972 if (player_is_moving && GfxElement[jx][jy] != EL_UNDEFINED)
1974 if (GFX_CRUMBLED(GfxElement[jx][jy]))
1975 DrawLevelFieldCrumbledSandDigging(jx, jy, move_dir, player->StepFrame);
1978 int old_element = GfxElement[jx][jy];
1979 int old_graphic = el_act_dir2img(old_element, action, move_dir);
1980 int frame = getGraphicAnimationFrame(old_graphic, player->StepFrame);
1982 DrawGraphic(sx, sy, old_graphic, frame);
1987 GfxElement[jx][jy] = EL_UNDEFINED;
1989 DrawLevelField(jx, jy);
1993 /* ----------------------------------------------------------------------- */
1994 /* draw player himself */
1995 /* ----------------------------------------------------------------------- */
1999 graphic = getPlayerGraphic(player, move_dir);
2001 /* in the case of changed player action or direction, prevent the current
2002 animation frame from being restarted for identical animations */
2003 if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic))
2004 player->Frame = last_player_frame;
2008 if (player->use_murphy_graphic)
2010 static int last_horizontal_dir = MV_LEFT;
2012 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
2013 last_horizontal_dir = move_dir;
2015 graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, move_dir);
2017 if (graphic == IMG_SP_MURPHY) /* undefined => use special graphic */
2019 int direction = (player->is_snapping ? move_dir : last_horizontal_dir);
2021 graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, direction);
2025 graphic = el_act_dir2img(player->element_nr, player->GfxAction, move_dir);
2029 frame = getGraphicAnimationFrame(graphic, player->Frame);
2033 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
2034 sxx = player->GfxPos;
2036 syy = player->GfxPos;
2039 if (!setup.soft_scrolling && ScreenMovPos)
2042 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
2044 if (SHIELD_ON(player))
2046 int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
2047 IMG_SHIELD_NORMAL_ACTIVE);
2048 int frame = getGraphicAnimationFrame(graphic, -1);
2050 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
2053 /* ----------------------------------------------------------------------- */
2054 /* draw things the player is pushing, if needed */
2055 /* ----------------------------------------------------------------------- */
2058 printf("::: %d, %d [%d, %d] [%d]\n",
2059 player->is_pushing, player_is_moving, player->GfxAction,
2060 player->is_moving, player_is_moving);
2064 if (player->is_pushing && player->is_moving)
2066 if (player->is_pushing && player_is_moving)
2070 int px = SCREENX(jx), py = SCREENY(jy);
2071 int pxx = (TILEX - ABS(sxx)) * dx;
2072 int pyy = (TILEY - ABS(syy)) * dy;
2074 int px = SCREENX(next_jx), py = SCREENY(next_jy);
2083 if (!IS_MOVING(jx, jy)) /* push movement already finished */
2084 element = Feld[next_jx][next_jy];
2086 graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
2087 frame = getGraphicAnimationFrame(graphic, player->StepFrame);
2089 /* draw background element under pushed element (like the Sokoban field) */
2090 if (Back[next_jx][next_jy])
2091 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
2093 /* masked drawing is needed for EMC style (double) movement graphics */
2094 DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame, NO_CUTTING);
2097 if (Back[next_jx][next_jy])
2098 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
2100 if ((pxx || pyy) && element == EL_SOKOBAN_OBJECT)
2101 DrawGraphicShiftedThruMask(px, py, pxx, pyy, IMG_SOKOBAN_OBJECT, 0,
2105 int element = MovingOrBlocked2Element(next_jx, next_jy);
2106 int graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
2108 int frame = getGraphicAnimationFrame(graphic, player->StepFrame);
2110 int frame = getGraphicAnimationFrame(graphic, player->Frame);
2114 /* masked drawing is needed for EMC style (double) movement graphics */
2115 DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame,
2118 DrawGraphicShifted(px, py, pxx, pyy, graphic, frame,
2119 NO_CUTTING, NO_MASKING);
2125 /* ----------------------------------------------------------------------- */
2126 /* draw things in front of player (active dynamite or dynabombs) */
2127 /* ----------------------------------------------------------------------- */
2129 if (IS_ACTIVE_BOMB(element))
2131 graphic = el2img(element);
2132 frame = getGraphicAnimationFrame(graphic, GfxFrame[jx][jy]);
2134 if (game.emulation == EMU_SUPAPLEX)
2135 DrawGraphic(sx, sy, IMG_SP_DISK_RED, frame);
2137 DrawGraphicThruMask(sx, sy, graphic, frame);
2140 if (player_is_moving && last_element == EL_EXPLOSION)
2142 int graphic = el_act2img(GfxElement[last_jx][last_jy], ACTION_EXPLODING);
2143 int delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2);
2144 int phase = ExplodePhase[last_jx][last_jy] - 1;
2145 int frame = getGraphicAnimationFrame(graphic, phase - delay);
2148 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy), graphic, frame);
2151 /* ----------------------------------------------------------------------- */
2152 /* draw elements the player is just walking/passing through/under */
2153 /* ----------------------------------------------------------------------- */
2155 if (player_is_moving)
2157 /* handle the field the player is leaving ... */
2158 if (IS_ACCESSIBLE_INSIDE(last_element))
2159 DrawLevelField(last_jx, last_jy);
2160 else if (IS_ACCESSIBLE_UNDER(last_element))
2161 DrawLevelFieldThruMask(last_jx, last_jy);
2165 /* do not redraw accessible elements if the player is just pushing them */
2166 if (!player_is_moving || !player->is_pushing)
2168 /* ... and the field the player is entering */
2169 if (IS_ACCESSIBLE_INSIDE(element))
2170 DrawLevelField(jx, jy);
2171 else if (IS_ACCESSIBLE_UNDER(element))
2172 DrawLevelFieldThruMask(jx, jy);
2178 /* !!! I have forgotton what this should be good for !!! */
2179 /* !!! causes player being visible when pushing from within tubes !!! */
2180 if (!player->is_pushing)
2183 /* ... and the field the player is entering */
2184 if (IS_ACCESSIBLE_INSIDE(element))
2185 DrawLevelField(jx, jy);
2186 else if (IS_ACCESSIBLE_UNDER(element))
2187 DrawLevelFieldThruMask(jx, jy);
2191 if (setup.direct_draw)
2193 int dst_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
2194 int dst_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
2195 int x_size = TILEX * (1 + ABS(jx - last_jx));
2196 int y_size = TILEY * (1 + ABS(jy - last_jy));
2198 BlitBitmap(drawto_field, window,
2199 dst_x, dst_y, x_size, y_size, dst_x, dst_y);
2200 SetDrawtoField(DRAW_DIRECT);
2203 MarkTileDirty(sx, sy);
2206 /* ------------------------------------------------------------------------- */
2208 void WaitForEventToContinue()
2210 boolean still_wait = TRUE;
2212 /* simulate releasing mouse button over last gadget, if still pressed */
2214 HandleGadgets(-1, -1, 0);
2216 button_status = MB_RELEASED;
2228 case EVENT_BUTTONPRESS:
2229 case EVENT_KEYPRESS:
2233 case EVENT_KEYRELEASE:
2234 ClearPlayerAction();
2238 HandleOtherEvents(&event);
2242 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2249 /* don't eat all CPU time */
2254 #define MAX_REQUEST_LINES 13
2255 #define MAX_REQUEST_LINE_FONT1_LEN 7
2256 #define MAX_REQUEST_LINE_FONT2_LEN 10
2258 boolean Request(char *text, unsigned int req_state)
2260 int mx, my, ty, result = -1;
2261 unsigned int old_door_state;
2262 int last_game_status = game_status; /* save current game status */
2263 int max_request_line_len = MAX_REQUEST_LINE_FONT1_LEN;
2264 int font_nr = FONT_TEXT_2;
2265 int max_word_len = 0;
2268 for (text_ptr = text; *text_ptr; text_ptr++)
2270 max_word_len = (*text_ptr != ' ' ? max_word_len + 1 : 0);
2272 if (max_word_len > MAX_REQUEST_LINE_FONT1_LEN)
2274 max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
2275 font_nr = FONT_LEVEL_NUMBER;
2282 if (game_status == GAME_MODE_PLAYING &&
2283 level.game_engine_type == GAME_ENGINE_TYPE_EM)
2284 BlitScreenToBitmap_EM(backbuffer);
2288 /* disable deactivated drawing when quick-loading level tape recording */
2289 if (tape.playing && tape.deactivate_display)
2290 TapeDeactivateDisplayOff(TRUE);
2294 SetMouseCursor(CURSOR_DEFAULT);
2297 #if defined(NETWORK_AVALIABLE)
2298 /* pause network game while waiting for request to answer */
2299 if (options.network &&
2300 game_status == GAME_MODE_PLAYING &&
2301 req_state & REQUEST_WAIT_FOR_INPUT)
2302 SendToServer_PausePlaying();
2305 old_door_state = GetDoorState();
2307 /* simulate releasing mouse button over last gadget, if still pressed */
2309 HandleGadgets(-1, -1, 0);
2313 if (old_door_state & DOOR_OPEN_1)
2315 CloseDoor(DOOR_CLOSE_1);
2317 /* save old door content */
2318 BlitBitmap(bitmap_db_door, bitmap_db_door,
2319 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
2320 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
2323 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
2325 /* clear door drawing field */
2326 DrawBackground(DX, DY, DXSIZE, DYSIZE);
2328 /* force DOOR font on preview level */
2329 game_status = GAME_MODE_PSEUDO_DOOR;
2331 /* write text for request */
2332 for (ty = 0; ty < MAX_REQUEST_LINES; ty++)
2334 char text_line[max_request_line_len + 1];
2340 for (tl = 0, tx = 0; tx < max_request_line_len; tl++, tx++)
2343 if (!tc || tc == ' ')
2354 strncpy(text_line, text, tl);
2357 DrawText(DX + (DXSIZE - tl * getFontWidth(font_nr)) / 2,
2358 DY + 8 + ty * (getFontHeight(font_nr) + 2),
2359 text_line, font_nr);
2361 text += tl + (tc == ' ' ? 1 : 0);
2364 game_status = last_game_status; /* restore current game status */
2366 if (req_state & REQ_ASK)
2368 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
2369 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
2371 else if (req_state & REQ_CONFIRM)
2373 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
2375 else if (req_state & REQ_PLAYER)
2377 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
2378 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
2379 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
2380 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
2383 /* copy request gadgets to door backbuffer */
2384 BlitBitmap(drawto, bitmap_db_door,
2385 DX, DY, DXSIZE, DYSIZE,
2386 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2388 OpenDoor(DOOR_OPEN_1);
2394 if (!(req_state & REQUEST_WAIT_FOR_INPUT))
2396 SetDrawBackgroundMask(REDRAW_FIELD);
2401 if (game_status != GAME_MODE_MAIN)
2404 button_status = MB_RELEASED;
2406 request_gadget_id = -1;
2408 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
2411 SetMouseCursor(CURSOR_DEFAULT);
2424 case EVENT_BUTTONPRESS:
2425 case EVENT_BUTTONRELEASE:
2426 case EVENT_MOTIONNOTIFY:
2428 if (event.type == EVENT_MOTIONNOTIFY)
2430 if (!PointerInWindow(window))
2431 continue; /* window and pointer are on different screens */
2436 motion_status = TRUE;
2437 mx = ((MotionEvent *) &event)->x;
2438 my = ((MotionEvent *) &event)->y;
2442 motion_status = FALSE;
2443 mx = ((ButtonEvent *) &event)->x;
2444 my = ((ButtonEvent *) &event)->y;
2445 if (event.type == EVENT_BUTTONPRESS)
2446 button_status = ((ButtonEvent *) &event)->button;
2448 button_status = MB_RELEASED;
2451 /* this sets 'request_gadget_id' */
2452 HandleGadgets(mx, my, button_status);
2454 switch(request_gadget_id)
2456 case TOOL_CTRL_ID_YES:
2459 case TOOL_CTRL_ID_NO:
2462 case TOOL_CTRL_ID_CONFIRM:
2463 result = TRUE | FALSE;
2466 case TOOL_CTRL_ID_PLAYER_1:
2469 case TOOL_CTRL_ID_PLAYER_2:
2472 case TOOL_CTRL_ID_PLAYER_3:
2475 case TOOL_CTRL_ID_PLAYER_4:
2486 case EVENT_KEYPRESS:
2487 switch(GetEventKey((KeyEvent *)&event, TRUE))
2500 if (req_state & REQ_PLAYER)
2504 case EVENT_KEYRELEASE:
2505 ClearPlayerAction();
2509 HandleOtherEvents(&event);
2513 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2515 int joy = AnyJoystick();
2517 if (joy & JOY_BUTTON_1)
2519 else if (joy & JOY_BUTTON_2)
2525 /* don't eat all CPU time */
2529 if (game_status != GAME_MODE_MAIN)
2534 if (!(req_state & REQ_STAY_OPEN))
2536 CloseDoor(DOOR_CLOSE_1);
2538 if (((old_door_state & DOOR_OPEN_1) && !(req_state & REQ_STAY_CLOSED)) ||
2539 (req_state & REQ_REOPEN))
2540 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
2545 SetDrawBackgroundMask(REDRAW_FIELD);
2547 #if defined(NETWORK_AVALIABLE)
2548 /* continue network game after request */
2549 if (options.network &&
2550 game_status == GAME_MODE_PLAYING &&
2551 req_state & REQUEST_WAIT_FOR_INPUT)
2552 SendToServer_ContinuePlaying();
2556 /* restore deactivated drawing when quick-loading level tape recording */
2557 if (tape.playing && tape.deactivate_display)
2558 TapeDeactivateDisplayOn();
2564 unsigned int OpenDoor(unsigned int door_state)
2566 if (door_state & DOOR_COPY_BACK)
2568 if (door_state & DOOR_OPEN_1)
2569 BlitBitmap(bitmap_db_door, bitmap_db_door,
2570 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
2571 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2573 if (door_state & DOOR_OPEN_2)
2574 BlitBitmap(bitmap_db_door, bitmap_db_door,
2575 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY2, VXSIZE, VYSIZE,
2576 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2578 door_state &= ~DOOR_COPY_BACK;
2581 return MoveDoor(door_state);
2584 unsigned int CloseDoor(unsigned int door_state)
2586 unsigned int old_door_state = GetDoorState();
2588 if (!(door_state & DOOR_NO_COPY_BACK))
2590 if (old_door_state & DOOR_OPEN_1)
2591 BlitBitmap(backbuffer, bitmap_db_door,
2592 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2594 if (old_door_state & DOOR_OPEN_2)
2595 BlitBitmap(backbuffer, bitmap_db_door,
2596 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2598 door_state &= ~DOOR_NO_COPY_BACK;
2601 return MoveDoor(door_state);
2604 unsigned int GetDoorState()
2606 return MoveDoor(DOOR_GET_STATE);
2609 unsigned int SetDoorState(unsigned int door_state)
2611 return MoveDoor(door_state | DOOR_SET_STATE);
2614 unsigned int MoveDoor(unsigned int door_state)
2616 static int door1 = DOOR_OPEN_1;
2617 static int door2 = DOOR_CLOSE_2;
2618 unsigned long door_delay = 0;
2619 unsigned long door_delay_value;
2622 if (door_state == DOOR_GET_STATE)
2623 return(door1 | door2);
2625 if (door_state & DOOR_SET_STATE)
2627 if (door_state & DOOR_ACTION_1)
2628 door1 = door_state & DOOR_ACTION_1;
2629 if (door_state & DOOR_ACTION_2)
2630 door2 = door_state & DOOR_ACTION_2;
2632 return(door1 | door2);
2635 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2636 door_state &= ~DOOR_OPEN_1;
2637 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2638 door_state &= ~DOOR_CLOSE_1;
2639 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2640 door_state &= ~DOOR_OPEN_2;
2641 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2642 door_state &= ~DOOR_CLOSE_2;
2644 door_delay_value = (door_state & DOOR_ACTION_1 ? door_1.step_delay :
2647 if (setup.quick_doors)
2649 stepsize = 20; /* must be choosen to always draw last frame */
2650 door_delay_value = 0;
2653 StopSound(SND_DOOR_OPENING);
2654 StopSound(SND_DOOR_CLOSING);
2658 if (global.autoplay_leveldir)
2660 door_state |= DOOR_NO_DELAY;
2661 door_state &= ~DOOR_CLOSE_ALL;
2664 if (door_state & DOOR_ACTION)
2666 boolean door_1_done = !(door_state & DOOR_ACTION_1);
2667 boolean door_2_done = !(door_state & DOOR_ACTION_2);
2668 int start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2669 int end = (door_state & DOOR_ACTION_1 &&
2670 door_1.anim_mode == ANIM_VERTICAL ? DYSIZE : DXSIZE);
2673 if (!(door_state & DOOR_NO_DELAY) && !setup.quick_doors)
2675 /* opening door sound has priority over simultaneously closing door */
2676 if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
2677 PlaySoundStereo(SND_DOOR_OPENING, SOUND_MIDDLE);
2678 else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
2679 PlaySoundStereo(SND_DOOR_CLOSING, SOUND_MIDDLE);
2682 for (x = start; x <= end && !(door_1_done && door_2_done); x += stepsize)
2684 Bitmap *bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2685 GC gc = bitmap->stored_clip_gc;
2687 if (door_state & DOOR_ACTION_1)
2689 int a = MIN(x * door_1.step_offset, end);
2690 int i = (door_state & DOOR_OPEN_1 ? end - a : a);
2694 BlitBitmap(bitmap_db_door, drawto,
2695 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i / 2,
2696 DXSIZE, DYSIZE - i / 2, DX, DY);
2698 ClearRectangle(drawto, DX, DY + DYSIZE - i / 2, DXSIZE, i / 2);
2701 if (door_1.anim_mode == ANIM_HORIZONTAL && x <= DXSIZE)
2703 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
2704 int dst1_x = DX + DXSIZE - i, dst1_y = DY;
2705 int src2_x = DXSIZE - i, src2_y = DOOR_GFX_PAGEY1;
2706 int dst2_x = DX, dst2_y = DY;
2707 int width = i, height = DYSIZE;
2709 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2710 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2713 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2714 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2717 else if (door_1.anim_mode == ANIM_VERTICAL && x <= DYSIZE)
2719 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
2720 int dst1_x = DX, dst1_y = DY + DYSIZE - i;
2721 int src2_x = 0, src2_y = DOOR_GFX_PAGEY1 + DYSIZE - i;
2722 int dst2_x = DX, dst2_y = DY;
2723 int width = DXSIZE, height = i;
2725 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2726 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2729 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2730 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2733 else if (x <= DXSIZE) /* ANIM_DEFAULT */
2735 int j = (door_1.anim_mode == ANIM_DEFAULT ? (DXSIZE - i) / 3 : 0);
2737 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2738 BlitBitmapMasked(bitmap, drawto,
2739 DXSIZE, DOOR_GFX_PAGEY1, i, 77,
2740 DX + DXSIZE - i, DY + j);
2741 BlitBitmapMasked(bitmap, drawto,
2742 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
2743 DX + DXSIZE - i, DY + 140 + j);
2744 SetClipOrigin(bitmap, gc, DX - DXSIZE + i,
2745 DY - (DOOR_GFX_PAGEY1 + j));
2746 BlitBitmapMasked(bitmap, drawto,
2747 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
2749 BlitBitmapMasked(bitmap, drawto,
2750 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
2753 BlitBitmapMasked(bitmap, drawto,
2754 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2756 BlitBitmapMasked(bitmap, drawto,
2757 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2759 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2760 BlitBitmapMasked(bitmap, drawto,
2761 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2762 DX + DXSIZE - i, DY + 77 + j);
2763 BlitBitmapMasked(bitmap, drawto,
2764 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2765 DX + DXSIZE - i, DY + 203 + j);
2768 redraw_mask |= REDRAW_DOOR_1;
2769 door_1_done = (a == end);
2772 if (door_state & DOOR_ACTION_2)
2774 int a = MIN(x * door_2.step_offset, VXSIZE);
2775 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - a : a);
2779 BlitBitmap(bitmap_db_door, drawto,
2780 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i / 2,
2781 VXSIZE, VYSIZE - i / 2, VX, VY);
2783 ClearRectangle(drawto, VX, VY + VYSIZE - i / 2, VXSIZE, i / 2);
2786 if (door_2.anim_mode == ANIM_HORIZONTAL && x <= VXSIZE)
2788 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
2789 int dst1_x = VX + VXSIZE - i, dst1_y = VY;
2790 int src2_x = VXSIZE - i, src2_y = DOOR_GFX_PAGEY2;
2791 int dst2_x = VX, dst2_y = VY;
2792 int width = i, height = VYSIZE;
2794 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2795 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2798 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2799 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2802 else if (door_2.anim_mode == ANIM_VERTICAL && x <= VYSIZE)
2804 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
2805 int dst1_x = VX, dst1_y = VY + VYSIZE - i;
2806 int src2_x = 0, src2_y = DOOR_GFX_PAGEY2 + VYSIZE - i;
2807 int dst2_x = VX, dst2_y = VY;
2808 int width = VXSIZE, height = i;
2810 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2811 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2814 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2815 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2818 else if (x <= VXSIZE) /* ANIM_DEFAULT */
2820 int j = (door_2.anim_mode == ANIM_DEFAULT ? (VXSIZE - i) / 3 : 0);
2822 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2823 BlitBitmapMasked(bitmap, drawto,
2824 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
2825 VX + VXSIZE - i, VY + j);
2826 SetClipOrigin(bitmap, gc,
2827 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2828 BlitBitmapMasked(bitmap, drawto,
2829 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
2832 BlitBitmapMasked(bitmap, drawto,
2833 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2834 i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
2835 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2836 BlitBitmapMasked(bitmap, drawto,
2837 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2839 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2842 redraw_mask |= REDRAW_DOOR_2;
2843 door_2_done = (a == VXSIZE);
2848 if (game_status == GAME_MODE_MAIN)
2851 if (!(door_state & DOOR_NO_DELAY))
2852 WaitUntilDelayReached(&door_delay, door_delay_value);
2857 if (setup.quick_doors)
2859 StopSound(SND_DOOR_OPENING);
2860 StopSound(SND_DOOR_CLOSING);
2864 if (door_state & DOOR_ACTION_1)
2865 door1 = door_state & DOOR_ACTION_1;
2866 if (door_state & DOOR_ACTION_2)
2867 door2 = door_state & DOOR_ACTION_2;
2869 return (door1 | door2);
2872 void DrawSpecialEditorDoor()
2874 /* draw bigger toolbox window */
2875 BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
2876 DOOR_GFX_PAGEX7, 0, EXSIZE + 8, 8,
2878 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2879 EX - 4, VY - 4, EXSIZE + 8, EYSIZE - VYSIZE + 4,
2882 redraw_mask |= REDRAW_ALL;
2885 void UndrawSpecialEditorDoor()
2887 /* draw normal tape recorder window */
2888 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2889 EX - 4, EY - 12, EXSIZE + 8, EYSIZE - VYSIZE + 12,
2892 redraw_mask |= REDRAW_ALL;
2896 /* ---------- new tool button stuff ---------------------------------------- */
2898 /* graphic position values for tool buttons */
2899 #define TOOL_BUTTON_YES_XPOS 2
2900 #define TOOL_BUTTON_YES_YPOS 250
2901 #define TOOL_BUTTON_YES_GFX_YPOS 0
2902 #define TOOL_BUTTON_YES_XSIZE 46
2903 #define TOOL_BUTTON_YES_YSIZE 28
2904 #define TOOL_BUTTON_NO_XPOS 52
2905 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2906 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2907 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2908 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2909 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2910 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2911 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2912 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2913 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2914 #define TOOL_BUTTON_PLAYER_XSIZE 30
2915 #define TOOL_BUTTON_PLAYER_YSIZE 30
2916 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2917 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2918 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2919 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2920 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2921 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2922 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2923 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2924 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2925 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2926 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2927 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2928 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2929 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2930 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2931 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2932 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2933 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2934 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2935 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2944 } toolbutton_info[NUM_TOOL_BUTTONS] =
2947 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2948 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2949 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2954 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2955 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2956 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2961 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2962 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2963 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2964 TOOL_CTRL_ID_CONFIRM,
2968 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2969 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2970 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2971 TOOL_CTRL_ID_PLAYER_1,
2975 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2976 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2977 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2978 TOOL_CTRL_ID_PLAYER_2,
2982 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2983 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2984 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2985 TOOL_CTRL_ID_PLAYER_3,
2989 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2990 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2991 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2992 TOOL_CTRL_ID_PLAYER_4,
2997 void CreateToolButtons()
3001 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
3003 Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
3004 Bitmap *deco_bitmap = None;
3005 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
3006 struct GadgetInfo *gi;
3007 unsigned long event_mask;
3008 int gd_xoffset, gd_yoffset;
3009 int gd_x1, gd_x2, gd_y;
3012 event_mask = GD_EVENT_RELEASED;
3014 gd_xoffset = toolbutton_info[i].xpos;
3015 gd_yoffset = toolbutton_info[i].ypos;
3016 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
3017 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
3018 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
3020 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
3022 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
3024 getMiniGraphicSource(PLAYER_NR_GFX(IMG_PLAYER_1, player_nr),
3025 &deco_bitmap, &deco_x, &deco_y);
3026 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
3027 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
3030 gi = CreateGadget(GDI_CUSTOM_ID, id,
3031 GDI_INFO_TEXT, toolbutton_info[i].infotext,
3032 GDI_X, DX + toolbutton_info[i].x,
3033 GDI_Y, DY + toolbutton_info[i].y,
3034 GDI_WIDTH, toolbutton_info[i].width,
3035 GDI_HEIGHT, toolbutton_info[i].height,
3036 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
3037 GDI_STATE, GD_BUTTON_UNPRESSED,
3038 GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
3039 GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
3040 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
3041 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
3042 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
3043 GDI_DECORATION_SHIFTING, 1, 1,
3044 GDI_EVENT_MASK, event_mask,
3045 GDI_CALLBACK_ACTION, HandleToolButtons,
3049 Error(ERR_EXIT, "cannot create gadget");
3051 tool_gadget[id] = gi;
3055 void FreeToolButtons()
3059 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
3060 FreeGadget(tool_gadget[i]);
3063 static void UnmapToolButtons()
3067 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
3068 UnmapGadget(tool_gadget[i]);
3071 static void HandleToolButtons(struct GadgetInfo *gi)
3073 request_gadget_id = gi->custom_id;
3078 static struct Mapping_EM_to_RND_object
3081 boolean is_rnd_to_em_mapping; /* unique mapping EM <-> RND */
3082 boolean is_backside; /* backside of moving element */
3088 em_object_mapping_list[] =
3091 Xblank, TRUE, FALSE,
3095 Yacid_splash_eB, FALSE, FALSE,
3096 EL_ACID_SPLASH_RIGHT, -1, -1
3099 Yacid_splash_wB, FALSE, FALSE,
3100 EL_ACID_SPLASH_LEFT, -1, -1
3103 #ifdef EM_ENGINE_BAD_ROLL
3105 Xstone_force_e, FALSE, FALSE,
3106 EL_ROCK, -1, MV_BIT_RIGHT
3109 Xstone_force_w, FALSE, FALSE,
3110 EL_ROCK, -1, MV_BIT_LEFT
3113 Xnut_force_e, FALSE, FALSE,
3114 EL_NUT, -1, MV_BIT_RIGHT
3117 Xnut_force_w, FALSE, FALSE,
3118 EL_NUT, -1, MV_BIT_LEFT
3121 Xspring_force_e, FALSE, FALSE,
3122 EL_SPRING, -1, MV_BIT_RIGHT
3125 Xspring_force_w, FALSE, FALSE,
3126 EL_SPRING, -1, MV_BIT_LEFT
3129 Xemerald_force_e, FALSE, FALSE,
3130 EL_EMERALD, -1, MV_BIT_RIGHT
3133 Xemerald_force_w, FALSE, FALSE,
3134 EL_EMERALD, -1, MV_BIT_LEFT
3137 Xdiamond_force_e, FALSE, FALSE,
3138 EL_DIAMOND, -1, MV_BIT_RIGHT
3141 Xdiamond_force_w, FALSE, FALSE,
3142 EL_DIAMOND, -1, MV_BIT_LEFT
3145 Xbomb_force_e, FALSE, FALSE,
3146 EL_BOMB, -1, MV_BIT_RIGHT
3149 Xbomb_force_w, FALSE, FALSE,
3150 EL_BOMB, -1, MV_BIT_LEFT
3152 #endif /* EM_ENGINE_BAD_ROLL */
3155 Xstone, TRUE, FALSE,
3159 Xstone_pause, FALSE, FALSE,
3163 Xstone_fall, FALSE, FALSE,
3167 Ystone_s, FALSE, FALSE,
3168 EL_ROCK, ACTION_FALLING, -1
3171 Ystone_sB, FALSE, TRUE,
3172 EL_ROCK, ACTION_FALLING, -1
3175 Ystone_e, FALSE, FALSE,
3176 EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT
3179 Ystone_eB, FALSE, TRUE,
3180 EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT
3183 Ystone_w, FALSE, FALSE,
3184 EL_ROCK, ACTION_MOVING, MV_BIT_LEFT
3187 Ystone_wB, FALSE, TRUE,
3188 EL_ROCK, ACTION_MOVING, MV_BIT_LEFT
3195 Xnut_pause, FALSE, FALSE,
3199 Xnut_fall, FALSE, FALSE,
3203 Ynut_s, FALSE, FALSE,
3204 EL_NUT, ACTION_FALLING, -1
3207 Ynut_sB, FALSE, TRUE,
3208 EL_NUT, ACTION_FALLING, -1
3211 Ynut_e, FALSE, FALSE,
3212 EL_NUT, ACTION_MOVING, MV_BIT_RIGHT
3215 Ynut_eB, FALSE, TRUE,
3216 EL_NUT, ACTION_MOVING, MV_BIT_RIGHT
3219 Ynut_w, FALSE, FALSE,
3220 EL_NUT, ACTION_MOVING, MV_BIT_LEFT
3223 Ynut_wB, FALSE, TRUE,
3224 EL_NUT, ACTION_MOVING, MV_BIT_LEFT
3227 Xbug_n, TRUE, FALSE,
3231 Xbug_e, TRUE, FALSE,
3232 EL_BUG_RIGHT, -1, -1
3235 Xbug_s, TRUE, FALSE,
3239 Xbug_w, TRUE, FALSE,
3243 Xbug_gon, FALSE, FALSE,
3247 Xbug_goe, FALSE, FALSE,
3248 EL_BUG_RIGHT, -1, -1
3251 Xbug_gos, FALSE, FALSE,
3255 Xbug_gow, FALSE, FALSE,
3259 Ybug_n, FALSE, FALSE,
3260 EL_BUG, ACTION_MOVING, MV_BIT_UP
3263 Ybug_nB, FALSE, TRUE,
3264 EL_BUG, ACTION_MOVING, MV_BIT_UP
3267 Ybug_e, FALSE, FALSE,
3268 EL_BUG, ACTION_MOVING, MV_BIT_RIGHT
3271 Ybug_eB, FALSE, TRUE,
3272 EL_BUG, ACTION_MOVING, MV_BIT_RIGHT
3275 Ybug_s, FALSE, FALSE,
3276 EL_BUG, ACTION_MOVING, MV_BIT_DOWN
3279 Ybug_sB, FALSE, TRUE,
3280 EL_BUG, ACTION_MOVING, MV_BIT_DOWN
3283 Ybug_w, FALSE, FALSE,
3284 EL_BUG, ACTION_MOVING, MV_BIT_LEFT
3287 Ybug_wB, FALSE, TRUE,
3288 EL_BUG, ACTION_MOVING, MV_BIT_LEFT
3291 Ybug_w_n, FALSE, FALSE,
3292 EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_UP
3295 Ybug_n_e, FALSE, FALSE,
3296 EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3299 Ybug_e_s, FALSE, FALSE,
3300 EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
3303 Ybug_s_w, FALSE, FALSE,
3304 EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3307 Ybug_e_n, FALSE, FALSE,
3308 EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
3311 Ybug_s_e, FALSE, FALSE,
3312 EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3315 Ybug_w_s, FALSE, FALSE,
3316 EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
3319 Ybug_n_w, FALSE, FALSE,
3320 EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3323 Ybug_stone, FALSE, FALSE,
3324 EL_BUG, ACTION_SMASHED_BY_ROCK, -1
3327 Ybug_spring, FALSE, FALSE,
3328 EL_BUG, ACTION_SMASHED_BY_SPRING, -1
3331 Xtank_n, TRUE, FALSE,
3332 EL_SPACESHIP_UP, -1, -1
3335 Xtank_e, TRUE, FALSE,
3336 EL_SPACESHIP_RIGHT, -1, -1
3339 Xtank_s, TRUE, FALSE,
3340 EL_SPACESHIP_DOWN, -1, -1
3343 Xtank_w, TRUE, FALSE,
3344 EL_SPACESHIP_LEFT, -1, -1
3347 Xtank_gon, FALSE, FALSE,
3348 EL_SPACESHIP_UP, -1, -1
3351 Xtank_goe, FALSE, FALSE,
3352 EL_SPACESHIP_RIGHT, -1, -1
3355 Xtank_gos, FALSE, FALSE,
3356 EL_SPACESHIP_DOWN, -1, -1
3359 Xtank_gow, FALSE, FALSE,
3360 EL_SPACESHIP_LEFT, -1, -1
3363 Ytank_n, FALSE, FALSE,
3364 EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP
3367 Ytank_nB, FALSE, TRUE,
3368 EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP
3371 Ytank_e, FALSE, FALSE,
3372 EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT
3375 Ytank_eB, FALSE, TRUE,
3376 EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT
3379 Ytank_s, FALSE, FALSE,
3380 EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN
3383 Ytank_sB, FALSE, TRUE,
3384 EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN
3387 Ytank_w, FALSE, FALSE,
3388 EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT
3391 Ytank_wB, FALSE, TRUE,
3392 EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT
3395 Ytank_w_n, FALSE, FALSE,
3396 EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_UP
3399 Ytank_n_e, FALSE, FALSE,
3400 EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3403 Ytank_e_s, FALSE, FALSE,
3404 EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
3407 Ytank_s_w, FALSE, FALSE,
3408 EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3411 Ytank_e_n, FALSE, FALSE,
3412 EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
3415 Ytank_s_e, FALSE, FALSE,
3416 EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3419 Ytank_w_s, FALSE, FALSE,
3420 EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
3423 Ytank_n_w, FALSE, FALSE,
3424 EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3427 Ytank_stone, FALSE, FALSE,
3428 EL_SPACESHIP, ACTION_SMASHED_BY_ROCK, -1
3431 Ytank_spring, FALSE, FALSE,
3432 EL_SPACESHIP, ACTION_SMASHED_BY_SPRING, -1
3435 Xandroid, TRUE, FALSE,
3436 EL_EMC_ANDROID, ACTION_ACTIVE, -1
3439 Xandroid_1_n, FALSE, FALSE,
3440 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_UP
3443 Xandroid_2_n, FALSE, FALSE,
3444 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_UP
3447 Xandroid_1_e, FALSE, FALSE,
3448 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_RIGHT
3451 Xandroid_2_e, FALSE, FALSE,
3452 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_RIGHT
3455 Xandroid_1_w, FALSE, FALSE,
3456 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_LEFT
3459 Xandroid_2_w, FALSE, FALSE,
3460 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_LEFT
3463 Xandroid_1_s, FALSE, FALSE,
3464 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_DOWN
3467 Xandroid_2_s, FALSE, FALSE,
3468 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_DOWN
3471 Yandroid_n, FALSE, FALSE,
3472 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_UP
3475 Yandroid_nB, FALSE, TRUE,
3476 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_UP
3479 Yandroid_ne, FALSE, FALSE,
3480 EL_EMC_ANDROID, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3483 Yandroid_neB, FALSE, TRUE,
3484 EL_EMC_ANDROID, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3487 Yandroid_e, FALSE, FALSE,
3488 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_RIGHT
3491 Yandroid_eB, FALSE, TRUE,
3492 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_RIGHT
3495 Yandroid_se, FALSE, FALSE,
3496 EL_EMC_ANDROID, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3499 Yandroid_seB, FALSE, TRUE,
3500 EL_EMC_ANDROID, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3503 Yandroid_s, FALSE, FALSE,
3504 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_DOWN
3507 Yandroid_sB, FALSE, TRUE,
3508 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_DOWN
3511 Yandroid_sw, FALSE, FALSE,
3512 EL_EMC_ANDROID, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3515 Yandroid_swB, FALSE, TRUE,
3516 EL_EMC_ANDROID, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3519 Yandroid_w, FALSE, FALSE,
3520 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_LEFT
3523 Yandroid_wB, FALSE, TRUE,
3524 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_LEFT
3527 Yandroid_nw, FALSE, FALSE,
3528 EL_EMC_ANDROID, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3531 Yandroid_nwB, FALSE, TRUE,
3532 EL_EMC_ANDROID, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3535 Xspring, TRUE, FALSE,
3539 Xspring_pause, FALSE, FALSE,
3543 Xspring_e, FALSE, FALSE,
3547 Xspring_w, FALSE, FALSE,
3551 Xspring_fall, FALSE, FALSE,
3555 Yspring_s, FALSE, FALSE,
3556 EL_SPRING, ACTION_FALLING, -1
3559 Yspring_sB, FALSE, TRUE,
3560 EL_SPRING, ACTION_FALLING, -1
3563 Yspring_e, FALSE, FALSE,
3564 EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT
3567 Yspring_eB, FALSE, TRUE,
3568 EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT
3571 Yspring_w, FALSE, FALSE,
3572 EL_SPRING, ACTION_MOVING, MV_BIT_LEFT
3575 Yspring_wB, FALSE, TRUE,
3576 EL_SPRING, ACTION_MOVING, MV_BIT_LEFT
3579 Yspring_kill_e, FALSE, FALSE,
3580 EL_ROBOT, ACTION_SLURPED_BY_SPRING, MV_BIT_RIGHT
3583 Yspring_kill_eB, FALSE, TRUE,
3584 EL_ROBOT, ACTION_SLURPED_BY_SPRING, MV_BIT_RIGHT
3587 Yspring_kill_w, FALSE, FALSE,
3588 EL_ROBOT, ACTION_SLURPED_BY_SPRING, MV_BIT_LEFT
3591 Yspring_kill_wB, FALSE, TRUE,
3592 EL_ROBOT, ACTION_SLURPED_BY_SPRING, MV_BIT_LEFT
3595 Xeater_n, TRUE, FALSE,
3599 Xeater_e, FALSE, FALSE,
3603 Xeater_w, FALSE, FALSE,
3607 Xeater_s, FALSE, FALSE,
3611 Yeater_n, FALSE, FALSE,
3612 EL_YAMYAM, ACTION_MOVING, MV_BIT_UP
3615 Yeater_nB, FALSE, TRUE,
3616 EL_YAMYAM, ACTION_MOVING, MV_BIT_UP
3619 Yeater_e, FALSE, FALSE,
3620 EL_YAMYAM, ACTION_MOVING, MV_BIT_RIGHT
3623 Yeater_eB, FALSE, TRUE,
3624 EL_YAMYAM, ACTION_MOVING, MV_BIT_RIGHT
3627 Yeater_s, FALSE, FALSE,
3628 EL_YAMYAM, ACTION_MOVING, MV_BIT_DOWN
3631 Yeater_sB, FALSE, TRUE,
3632 EL_YAMYAM, ACTION_MOVING, MV_BIT_DOWN
3635 Yeater_w, FALSE, FALSE,
3636 EL_YAMYAM, ACTION_MOVING, MV_BIT_LEFT
3639 Yeater_wB, FALSE, TRUE,
3640 EL_YAMYAM, ACTION_MOVING, MV_BIT_LEFT
3643 Yeater_stone, FALSE, FALSE,
3644 EL_YAMYAM, ACTION_SMASHED_BY_ROCK, -1
3647 Yeater_spring, FALSE, FALSE,
3648 EL_YAMYAM, ACTION_SMASHED_BY_SPRING, -1
3651 Xalien, TRUE, FALSE,
3655 Xalien_pause, FALSE, FALSE,
3659 Yalien_n, FALSE, FALSE,
3660 EL_ROBOT, ACTION_MOVING, MV_BIT_UP
3663 Yalien_nB, FALSE, TRUE,
3664 EL_ROBOT, ACTION_MOVING, MV_BIT_UP
3667 Yalien_e, FALSE, FALSE,
3668 EL_ROBOT, ACTION_MOVING, MV_BIT_RIGHT
3671 Yalien_eB, FALSE, TRUE,
3672 EL_ROBOT, ACTION_MOVING, MV_BIT_RIGHT
3675 Yalien_s, FALSE, FALSE,
3676 EL_ROBOT, ACTION_MOVING, MV_BIT_DOWN
3679 Yalien_sB, FALSE, TRUE,
3680 EL_ROBOT, ACTION_MOVING, MV_BIT_DOWN
3683 Yalien_w, FALSE, FALSE,
3684 EL_ROBOT, ACTION_MOVING, MV_BIT_LEFT
3687 Yalien_wB, FALSE, TRUE,
3688 EL_ROBOT, ACTION_MOVING, MV_BIT_LEFT
3691 Yalien_stone, FALSE, FALSE,
3692 EL_ROBOT, ACTION_SMASHED_BY_ROCK, -1
3695 Yalien_spring, FALSE, FALSE,
3696 EL_ROBOT, ACTION_SMASHED_BY_SPRING, -1
3699 Xemerald, TRUE, FALSE,
3703 Xemerald_pause, FALSE, FALSE,
3707 Xemerald_fall, FALSE, FALSE,
3711 Xemerald_shine, FALSE, FALSE,
3712 EL_EMERALD, ACTION_TWINKLING, -1
3715 Yemerald_s, FALSE, FALSE,
3716 EL_EMERALD, ACTION_FALLING, -1
3719 Yemerald_sB, FALSE, TRUE,
3720 EL_EMERALD, ACTION_FALLING, -1
3723 Yemerald_e, FALSE, FALSE,
3724 EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT
3727 Yemerald_eB, FALSE, TRUE,
3728 EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT
3731 Yemerald_w, FALSE, FALSE,
3732 EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT
3735 Yemerald_wB, FALSE, TRUE,
3736 EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT
3739 Yemerald_eat, FALSE, FALSE,
3740 EL_EMERALD, ACTION_COLLECTING, -1
3743 Yemerald_stone, FALSE, FALSE,
3744 EL_NUT, ACTION_BREAKING, -1
3747 Xdiamond, TRUE, FALSE,
3751 Xdiamond_pause, FALSE, FALSE,
3755 Xdiamond_fall, FALSE, FALSE,
3759 Xdiamond_shine, FALSE, FALSE,
3760 EL_DIAMOND, ACTION_TWINKLING, -1
3763 Ydiamond_s, FALSE, FALSE,
3764 EL_DIAMOND, ACTION_FALLING, -1
3767 Ydiamond_sB, FALSE, TRUE,
3768 EL_DIAMOND, ACTION_FALLING, -1
3771 Ydiamond_e, FALSE, FALSE,
3772 EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT
3775 Ydiamond_eB, FALSE, TRUE,
3776 EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT
3779 Ydiamond_w, FALSE, FALSE,
3780 EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT
3783 Ydiamond_wB, FALSE, TRUE,
3784 EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT
3787 Ydiamond_eat, FALSE, FALSE,
3788 EL_DIAMOND, ACTION_COLLECTING, -1
3791 Ydiamond_stone, FALSE, FALSE,
3792 EL_DIAMOND, ACTION_SMASHED_BY_ROCK, -1
3795 Xdrip_fall, TRUE, FALSE,
3796 EL_AMOEBA_DROP, -1, -1
3799 Xdrip_stretch, FALSE, FALSE,
3800 EL_AMOEBA_DROP, ACTION_FALLING, -1
3803 Xdrip_stretchB, FALSE, TRUE,
3804 EL_AMOEBA_DROP, ACTION_FALLING, -1
3807 Xdrip_eat, FALSE, FALSE,
3808 EL_AMOEBA_DROP, ACTION_GROWING, -1
3811 Ydrip_s1, FALSE, FALSE,
3812 EL_AMOEBA_DROP, ACTION_FALLING, -1
3815 Ydrip_s1B, FALSE, TRUE,
3816 EL_AMOEBA_DROP, ACTION_FALLING, -1
3819 Ydrip_s2, FALSE, FALSE,
3820 EL_AMOEBA_DROP, ACTION_FALLING, -1
3823 Ydrip_s2B, FALSE, TRUE,
3824 EL_AMOEBA_DROP, ACTION_FALLING, -1
3831 Xbomb_pause, FALSE, FALSE,
3835 Xbomb_fall, FALSE, FALSE,
3839 Ybomb_s, FALSE, FALSE,
3840 EL_BOMB, ACTION_FALLING, -1
3843 Ybomb_sB, FALSE, TRUE,
3844 EL_BOMB, ACTION_FALLING, -1
3847 Ybomb_e, FALSE, FALSE,
3848 EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT
3851 Ybomb_eB, FALSE, TRUE,
3852 EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT
3855 Ybomb_w, FALSE, FALSE,
3856 EL_BOMB, ACTION_MOVING, MV_BIT_LEFT
3859 Ybomb_wB, FALSE, TRUE,
3860 EL_BOMB, ACTION_MOVING, MV_BIT_LEFT
3863 Ybomb_eat, FALSE, FALSE,
3864 EL_BOMB, ACTION_ACTIVATING, -1
3867 Xballoon, TRUE, FALSE,
3871 Yballoon_n, FALSE, FALSE,
3872 EL_BALLOON, ACTION_MOVING, MV_BIT_UP
3875 Yballoon_nB, FALSE, TRUE,
3876 EL_BALLOON, ACTION_MOVING, MV_BIT_UP
3879 Yballoon_e, FALSE, FALSE,
3880 EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT
3883 Yballoon_eB, FALSE, TRUE,
3884 EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT
3887 Yballoon_s, FALSE, FALSE,
3888 EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN
3891 Yballoon_sB, FALSE, TRUE,
3892 EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN
3895 Yballoon_w, FALSE, FALSE,
3896 EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT
3899 Yballoon_wB, FALSE, TRUE,
3900 EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT
3903 Xgrass, TRUE, FALSE,
3904 EL_EMC_GRASS, -1, -1
3907 Ygrass_nB, FALSE, FALSE,
3908 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_UP
3911 Ygrass_eB, FALSE, FALSE,
3912 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_RIGHT
3915 Ygrass_sB, FALSE, FALSE,
3916 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_DOWN
3919 Ygrass_wB, FALSE, FALSE,
3920 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_LEFT
3927 Ydirt_nB, FALSE, FALSE,
3928 EL_SAND, ACTION_DIGGING, MV_BIT_UP
3931 Ydirt_eB, FALSE, FALSE,
3932 EL_SAND, ACTION_DIGGING, MV_BIT_RIGHT
3935 Ydirt_sB, FALSE, FALSE,
3936 EL_SAND, ACTION_DIGGING, MV_BIT_DOWN
3939 Ydirt_wB, FALSE, FALSE,
3940 EL_SAND, ACTION_DIGGING, MV_BIT_LEFT
3943 Xacid_ne, TRUE, FALSE,
3944 EL_ACID_POOL_TOPRIGHT, -1, -1
3947 Xacid_se, TRUE, FALSE,
3948 EL_ACID_POOL_BOTTOMRIGHT, -1, -1
3951 Xacid_s, TRUE, FALSE,
3952 EL_ACID_POOL_BOTTOM, -1, -1
3955 Xacid_sw, TRUE, FALSE,
3956 EL_ACID_POOL_BOTTOMLEFT, -1, -1
3959 Xacid_nw, TRUE, FALSE,
3960 EL_ACID_POOL_TOPLEFT, -1, -1
3963 Xacid_1, TRUE, FALSE,
3967 Xacid_2, FALSE, FALSE,
3971 Xacid_3, FALSE, FALSE,
3975 Xacid_4, FALSE, FALSE,
3979 Xacid_5, FALSE, FALSE,
3983 Xacid_6, FALSE, FALSE,
3987 Xacid_7, FALSE, FALSE,
3991 Xacid_8, FALSE, FALSE,
3995 Xball_1, TRUE, FALSE,
3996 EL_EMC_MAGIC_BALL, -1, -1
3999 Xball_1B, FALSE, FALSE,
4000 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
4003 Xball_2, FALSE, FALSE,
4004 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
4007 Xball_2B, FALSE, FALSE,
4008 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
4011 Yball_eat, FALSE, FALSE,
4012 EL_EMC_MAGIC_BALL, ACTION_DROPPING, -1
4015 Ykey_1_eat, FALSE, FALSE,
4016 EL_EM_KEY_1, ACTION_COLLECTING, -1
4019 Ykey_2_eat, FALSE, FALSE,
4020 EL_EM_KEY_2, ACTION_COLLECTING, -1
4023 Ykey_3_eat, FALSE, FALSE,
4024 EL_EM_KEY_3, ACTION_COLLECTING, -1
4027 Ykey_4_eat, FALSE, FALSE,
4028 EL_EM_KEY_4, ACTION_COLLECTING, -1
4031 Ykey_5_eat, FALSE, FALSE,
4032 EL_EMC_KEY_5, ACTION_COLLECTING, -1
4035 Ykey_6_eat, FALSE, FALSE,
4036 EL_EMC_KEY_6, ACTION_COLLECTING, -1
4039 Ykey_7_eat, FALSE, FALSE,
4040 EL_EMC_KEY_7, ACTION_COLLECTING, -1
4043 Ykey_8_eat, FALSE, FALSE,
4044 EL_EMC_KEY_8, ACTION_COLLECTING, -1
4047 Ylenses_eat, FALSE, FALSE,
4048 EL_EMC_LENSES, ACTION_COLLECTING, -1
4051 Ymagnify_eat, FALSE, FALSE,
4052 EL_EMC_MAGNIFIER, ACTION_COLLECTING, -1
4055 Ygrass_eat, FALSE, FALSE,
4056 EL_EMC_GRASS, ACTION_SNAPPING, -1
4059 Ydirt_eat, FALSE, FALSE,
4060 EL_SAND, ACTION_SNAPPING, -1
4063 Xgrow_ns, TRUE, FALSE,
4064 EL_EXPANDABLE_WALL_VERTICAL, -1, -1
4067 Ygrow_ns_eat, FALSE, FALSE,
4068 EL_EXPANDABLE_WALL_VERTICAL, ACTION_GROWING, -1
4071 Xgrow_ew, TRUE, FALSE,
4072 EL_EXPANDABLE_WALL_HORIZONTAL, -1, -1
4075 Ygrow_ew_eat, FALSE, FALSE,
4076 EL_EXPANDABLE_WALL_HORIZONTAL, ACTION_GROWING, -1
4079 Xwonderwall, TRUE, FALSE,
4080 EL_MAGIC_WALL, -1, -1
4083 XwonderwallB, FALSE, FALSE,
4084 EL_MAGIC_WALL, ACTION_ACTIVE, -1
4087 Xamoeba_1, TRUE, FALSE,
4088 EL_AMOEBA_DRY, ACTION_OTHER, -1
4091 Xamoeba_2, FALSE, FALSE,
4092 EL_AMOEBA_DRY, ACTION_OTHER, -1
4095 Xamoeba_3, FALSE, FALSE,
4096 EL_AMOEBA_DRY, ACTION_OTHER, -1
4099 Xamoeba_4, FALSE, FALSE,
4100 EL_AMOEBA_DRY, ACTION_OTHER, -1
4103 Xamoeba_5, TRUE, FALSE,
4104 EL_AMOEBA_WET, ACTION_OTHER, -1
4107 Xamoeba_6, FALSE, FALSE,
4108 EL_AMOEBA_WET, ACTION_OTHER, -1
4111 Xamoeba_7, FALSE, FALSE,
4112 EL_AMOEBA_WET, ACTION_OTHER, -1
4115 Xamoeba_8, FALSE, FALSE,
4116 EL_AMOEBA_WET, ACTION_OTHER, -1
4119 Xdoor_1, TRUE, FALSE,
4120 EL_EM_GATE_1, -1, -1
4123 Xdoor_2, TRUE, FALSE,
4124 EL_EM_GATE_2, -1, -1
4127 Xdoor_3, TRUE, FALSE,
4128 EL_EM_GATE_3, -1, -1
4131 Xdoor_4, TRUE, FALSE,
4132 EL_EM_GATE_4, -1, -1
4135 Xdoor_5, TRUE, FALSE,
4136 EL_EMC_GATE_5, -1, -1
4139 Xdoor_6, TRUE, FALSE,
4140 EL_EMC_GATE_6, -1, -1
4143 Xdoor_7, TRUE, FALSE,
4144 EL_EMC_GATE_7, -1, -1
4147 Xdoor_8, TRUE, FALSE,
4148 EL_EMC_GATE_8, -1, -1
4151 Xkey_1, TRUE, FALSE,
4155 Xkey_2, TRUE, FALSE,
4159 Xkey_3, TRUE, FALSE,
4163 Xkey_4, TRUE, FALSE,
4167 Xkey_5, TRUE, FALSE,
4168 EL_EMC_KEY_5, -1, -1
4171 Xkey_6, TRUE, FALSE,
4172 EL_EMC_KEY_6, -1, -1
4175 Xkey_7, TRUE, FALSE,
4176 EL_EMC_KEY_7, -1, -1
4179 Xkey_8, TRUE, FALSE,
4180 EL_EMC_KEY_8, -1, -1
4183 Xwind_n, TRUE, FALSE,
4184 EL_BALLOON_SWITCH_UP, -1, -1
4187 Xwind_e, TRUE, FALSE,
4188 EL_BALLOON_SWITCH_RIGHT, -1, -1
4191 Xwind_s, TRUE, FALSE,
4192 EL_BALLOON_SWITCH_DOWN, -1, -1
4195 Xwind_w, TRUE, FALSE,
4196 EL_BALLOON_SWITCH_LEFT, -1, -1
4199 Xwind_nesw, TRUE, FALSE,
4200 EL_BALLOON_SWITCH_ANY, -1, -1
4203 Xwind_stop, TRUE, FALSE,
4204 EL_BALLOON_SWITCH_NONE, -1, -1
4208 EL_EXIT_CLOSED, -1, -1
4211 Xexit_1, TRUE, FALSE,
4212 EL_EXIT_OPEN, -1, -1
4215 Xexit_2, FALSE, FALSE,
4216 EL_EXIT_OPEN, -1, -1
4219 Xexit_3, FALSE, FALSE,
4220 EL_EXIT_OPEN, -1, -1
4223 Xdynamite, TRUE, FALSE,
4227 Ydynamite_eat, FALSE, FALSE,
4228 EL_DYNAMITE, ACTION_COLLECTING, -1
4231 Xdynamite_1, TRUE, FALSE,
4232 EL_DYNAMITE_ACTIVE, -1, -1
4235 Xdynamite_2, FALSE, FALSE,
4236 EL_DYNAMITE_ACTIVE, -1, -1
4239 Xdynamite_3, FALSE, FALSE,
4240 EL_DYNAMITE_ACTIVE, -1, -1
4243 Xdynamite_4, FALSE, FALSE,
4244 EL_DYNAMITE_ACTIVE, -1, -1
4247 Xbumper, TRUE, FALSE,
4248 EL_EMC_SPRING_BUMPER, -1, -1
4251 XbumperB, FALSE, FALSE,
4252 EL_EMC_SPRING_BUMPER, ACTION_ACTIVE, -1
4255 Xwheel, TRUE, FALSE,
4256 EL_ROBOT_WHEEL, -1, -1
4259 XwheelB, FALSE, FALSE,
4260 EL_ROBOT_WHEEL, ACTION_ACTIVE, -1
4263 Xswitch, TRUE, FALSE,
4264 EL_EMC_MAGIC_BALL_SWITCH, -1, -1
4267 XswitchB, FALSE, FALSE,
4268 EL_EMC_MAGIC_BALL_SWITCH, ACTION_ACTIVE, -1
4272 EL_QUICKSAND_EMPTY, -1, -1
4275 Xsand_stone, TRUE, FALSE,
4276 EL_QUICKSAND_FULL, -1, -1
4279 Xsand_stonein_1, FALSE, FALSE,
4280 EL_ROCK, ACTION_FILLING, -1
4283 Xsand_stonein_2, FALSE, FALSE,
4284 EL_ROCK, ACTION_FILLING, -1
4287 Xsand_stonein_3, FALSE, FALSE,
4288 EL_ROCK, ACTION_FILLING, -1
4291 Xsand_stonein_4, FALSE, FALSE,
4292 EL_ROCK, ACTION_FILLING, -1
4295 Xsand_stonesand_1, FALSE, FALSE,
4296 EL_QUICKSAND_FULL, -1, -1
4299 Xsand_stonesand_2, FALSE, FALSE,
4300 EL_QUICKSAND_FULL, -1, -1
4303 Xsand_stonesand_3, FALSE, FALSE,
4304 EL_QUICKSAND_FULL, -1, -1
4307 Xsand_stonesand_4, FALSE, FALSE,
4308 EL_QUICKSAND_FULL, -1, -1
4311 Xsand_stoneout_1, FALSE, FALSE,
4312 EL_ROCK, ACTION_EMPTYING, -1
4315 Xsand_stoneout_2, FALSE, FALSE,
4316 EL_ROCK, ACTION_EMPTYING, -1
4319 Xsand_sandstone_1, FALSE, FALSE,
4320 EL_QUICKSAND_FULL, -1, -1
4323 Xsand_sandstone_2, FALSE, FALSE,
4324 EL_QUICKSAND_FULL, -1, -1
4327 Xsand_sandstone_3, FALSE, FALSE,
4328 EL_QUICKSAND_FULL, -1, -1
4331 Xsand_sandstone_4, FALSE, FALSE,
4332 EL_QUICKSAND_FULL, -1, -1
4335 Xplant, TRUE, FALSE,
4336 EL_EMC_PLANT, -1, -1
4339 Yplant, FALSE, FALSE,
4340 EL_EMC_PLANT, -1, -1
4343 Xlenses, TRUE, FALSE,
4344 EL_EMC_LENSES, -1, -1
4347 Xmagnify, TRUE, FALSE,
4348 EL_EMC_MAGNIFIER, -1, -1
4351 Xdripper, TRUE, FALSE,
4352 EL_EMC_DRIPPER, -1, -1
4355 XdripperB, FALSE, FALSE,
4356 EL_EMC_DRIPPER, ACTION_ACTIVE, -1
4359 Xfake_blank, TRUE, FALSE,
4360 EL_INVISIBLE_WALL, -1, -1
4363 Xfake_blankB, FALSE, FALSE,
4364 EL_INVISIBLE_WALL, ACTION_ACTIVE, -1
4367 Xfake_grass, TRUE, FALSE,
4368 EL_EMC_FAKE_GRASS, -1, -1
4371 Xfake_grassB, FALSE, FALSE,
4372 EL_EMC_FAKE_GRASS, ACTION_ACTIVE, -1
4375 Xfake_door_1, TRUE, FALSE,
4376 EL_EM_GATE_1_GRAY, -1, -1
4379 Xfake_door_2, TRUE, FALSE,
4380 EL_EM_GATE_2_GRAY, -1, -1
4383 Xfake_door_3, TRUE, FALSE,
4384 EL_EM_GATE_3_GRAY, -1, -1
4387 Xfake_door_4, TRUE, FALSE,
4388 EL_EM_GATE_4_GRAY, -1, -1
4391 Xfake_door_5, TRUE, FALSE,
4392 EL_EMC_GATE_5_GRAY, -1, -1
4395 Xfake_door_6, TRUE, FALSE,
4396 EL_EMC_GATE_6_GRAY, -1, -1
4399 Xfake_door_7, TRUE, FALSE,
4400 EL_EMC_GATE_7_GRAY, -1, -1
4403 Xfake_door_8, TRUE, FALSE,
4404 EL_EMC_GATE_8_GRAY, -1, -1
4407 Xfake_acid_1, TRUE, FALSE,
4408 EL_EMC_FAKE_ACID, -1, -1
4411 Xfake_acid_2, FALSE, FALSE,
4412 EL_EMC_FAKE_ACID, -1, -1
4415 Xfake_acid_3, FALSE, FALSE,
4416 EL_EMC_FAKE_ACID, -1, -1
4419 Xfake_acid_4, FALSE, FALSE,
4420 EL_EMC_FAKE_ACID, -1, -1
4423 Xfake_acid_5, FALSE, FALSE,
4424 EL_EMC_FAKE_ACID, -1, -1
4427 Xfake_acid_6, FALSE, FALSE,
4428 EL_EMC_FAKE_ACID, -1, -1
4431 Xfake_acid_7, FALSE, FALSE,
4432 EL_EMC_FAKE_ACID, -1, -1
4435 Xfake_acid_8, FALSE, FALSE,
4436 EL_EMC_FAKE_ACID, -1, -1
4439 Xsteel_1, TRUE, FALSE,
4440 EL_STEELWALL, -1, -1
4443 Xsteel_2, TRUE, FALSE,
4444 EL_EMC_STEELWALL_2, -1, -1
4447 Xsteel_3, TRUE, FALSE,
4448 EL_EMC_STEELWALL_3, -1, -1
4451 Xsteel_4, TRUE, FALSE,
4452 EL_EMC_STEELWALL_4, -1, -1
4455 Xwall_1, TRUE, FALSE,
4459 Xwall_2, TRUE, FALSE,
4460 EL_EMC_WALL_14, -1, -1
4463 Xwall_3, TRUE, FALSE,
4464 EL_EMC_WALL_15, -1, -1
4467 Xwall_4, TRUE, FALSE,
4468 EL_EMC_WALL_16, -1, -1
4471 Xround_wall_1, TRUE, FALSE,
4472 EL_WALL_SLIPPERY, -1, -1
4475 Xround_wall_2, TRUE, FALSE,
4476 EL_EMC_WALL_SLIPPERY_2, -1, -1
4479 Xround_wall_3, TRUE, FALSE,
4480 EL_EMC_WALL_SLIPPERY_3, -1, -1
4483 Xround_wall_4, TRUE, FALSE,
4484 EL_EMC_WALL_SLIPPERY_4, -1, -1
4487 Xdecor_1, TRUE, FALSE,
4488 EL_EMC_WALL_8, -1, -1
4491 Xdecor_2, TRUE, FALSE,
4492 EL_EMC_WALL_6, -1, -1
4495 Xdecor_3, TRUE, FALSE,
4496 EL_EMC_WALL_4, -1, -1
4499 Xdecor_4, TRUE, FALSE,
4500 EL_EMC_WALL_7, -1, -1
4503 Xdecor_5, TRUE, FALSE,
4504 EL_EMC_WALL_5, -1, -1
4507 Xdecor_6, TRUE, FALSE,
4508 EL_EMC_WALL_9, -1, -1
4511 Xdecor_7, TRUE, FALSE,
4512 EL_EMC_WALL_10, -1, -1
4515 Xdecor_8, TRUE, FALSE,
4516 EL_EMC_WALL_1, -1, -1
4519 Xdecor_9, TRUE, FALSE,
4520 EL_EMC_WALL_2, -1, -1
4523 Xdecor_10, TRUE, FALSE,
4524 EL_EMC_WALL_3, -1, -1
4527 Xdecor_11, TRUE, FALSE,
4528 EL_EMC_WALL_11, -1, -1
4531 Xdecor_12, TRUE, FALSE,
4532 EL_EMC_WALL_12, -1, -1
4535 Xalpha_0, TRUE, FALSE,
4536 EL_CHAR('0'), -1, -1
4539 Xalpha_1, TRUE, FALSE,
4540 EL_CHAR('1'), -1, -1
4543 Xalpha_2, TRUE, FALSE,
4544 EL_CHAR('2'), -1, -1
4547 Xalpha_3, TRUE, FALSE,
4548 EL_CHAR('3'), -1, -1
4551 Xalpha_4, TRUE, FALSE,
4552 EL_CHAR('4'), -1, -1
4555 Xalpha_5, TRUE, FALSE,
4556 EL_CHAR('5'), -1, -1
4559 Xalpha_6, TRUE, FALSE,
4560 EL_CHAR('6'), -1, -1
4563 Xalpha_7, TRUE, FALSE,
4564 EL_CHAR('7'), -1, -1
4567 Xalpha_8, TRUE, FALSE,
4568 EL_CHAR('8'), -1, -1
4571 Xalpha_9, TRUE, FALSE,
4572 EL_CHAR('9'), -1, -1
4575 Xalpha_excla, TRUE, FALSE,
4576 EL_CHAR('!'), -1, -1
4579 Xalpha_quote, TRUE, FALSE,
4580 EL_CHAR('"'), -1, -1
4583 Xalpha_comma, TRUE, FALSE,
4584 EL_CHAR(','), -1, -1
4587 Xalpha_minus, TRUE, FALSE,
4588 EL_CHAR('-'), -1, -1
4591 Xalpha_perio, TRUE, FALSE,
4592 EL_CHAR('.'), -1, -1
4595 Xalpha_colon, TRUE, FALSE,
4596 EL_CHAR(':'), -1, -1
4599 Xalpha_quest, TRUE, FALSE,
4600 EL_CHAR('?'), -1, -1
4603 Xalpha_a, TRUE, FALSE,
4604 EL_CHAR('A'), -1, -1
4607 Xalpha_b, TRUE, FALSE,
4608 EL_CHAR('B'), -1, -1
4611 Xalpha_c, TRUE, FALSE,
4612 EL_CHAR('C'), -1, -1
4615 Xalpha_d, TRUE, FALSE,
4616 EL_CHAR('D'), -1, -1
4619 Xalpha_e, TRUE, FALSE,
4620 EL_CHAR('E'), -1, -1
4623 Xalpha_f, TRUE, FALSE,
4624 EL_CHAR('F'), -1, -1
4627 Xalpha_g, TRUE, FALSE,
4628 EL_CHAR('G'), -1, -1
4631 Xalpha_h, TRUE, FALSE,
4632 EL_CHAR('H'), -1, -1
4635 Xalpha_i, TRUE, FALSE,
4636 EL_CHAR('I'), -1, -1
4639 Xalpha_j, TRUE, FALSE,
4640 EL_CHAR('J'), -1, -1
4643 Xalpha_k, TRUE, FALSE,
4644 EL_CHAR('K'), -1, -1
4647 Xalpha_l, TRUE, FALSE,
4648 EL_CHAR('L'), -1, -1
4651 Xalpha_m, TRUE, FALSE,
4652 EL_CHAR('M'), -1, -1
4655 Xalpha_n, TRUE, FALSE,
4656 EL_CHAR('N'), -1, -1
4659 Xalpha_o, TRUE, FALSE,
4660 EL_CHAR('O'), -1, -1
4663 Xalpha_p, TRUE, FALSE,
4664 EL_CHAR('P'), -1, -1
4667 Xalpha_q, TRUE, FALSE,
4668 EL_CHAR('Q'), -1, -1
4671 Xalpha_r, TRUE, FALSE,
4672 EL_CHAR('R'), -1, -1
4675 Xalpha_s, TRUE, FALSE,
4676 EL_CHAR('S'), -1, -1
4679 Xalpha_t, TRUE, FALSE,
4680 EL_CHAR('T'), -1, -1
4683 Xalpha_u, TRUE, FALSE,
4684 EL_CHAR('U'), -1, -1
4687 Xalpha_v, TRUE, FALSE,
4688 EL_CHAR('V'), -1, -1
4691 Xalpha_w, TRUE, FALSE,
4692 EL_CHAR('W'), -1, -1
4695 Xalpha_x, TRUE, FALSE,
4696 EL_CHAR('X'), -1, -1
4699 Xalpha_y, TRUE, FALSE,
4700 EL_CHAR('Y'), -1, -1
4703 Xalpha_z, TRUE, FALSE,
4704 EL_CHAR('Z'), -1, -1
4707 Xalpha_arrow_e, TRUE, FALSE,
4708 EL_CHAR('>'), -1, -1
4711 Xalpha_arrow_w, TRUE, FALSE,
4712 EL_CHAR('<'), -1, -1
4715 Xalpha_copyr, TRUE, FALSE,
4716 EL_CHAR('©'), -1, -1
4719 Xalpha_copyr, TRUE, FALSE,
4720 EL_CHAR('©'), -1, -1
4724 Xboom_bug, FALSE, FALSE,
4725 EL_BUG, ACTION_EXPLODING, -1
4728 Xboom_bomb, FALSE, FALSE,
4729 EL_BOMB, ACTION_EXPLODING, -1
4732 Xboom_android, FALSE, FALSE,
4733 EL_EMC_ANDROID, ACTION_OTHER, -1
4736 Xboom_1, FALSE, FALSE,
4737 EL_DEFAULT, ACTION_EXPLODING, -1
4740 Xboom_2, FALSE, FALSE,
4741 EL_DEFAULT, ACTION_EXPLODING, -1
4744 Znormal, FALSE, FALSE,
4748 Zdynamite, FALSE, FALSE,
4752 Zplayer, FALSE, FALSE,
4756 ZBORDER, FALSE, FALSE,
4766 static struct Mapping_EM_to_RND_player
4775 em_player_mapping_list[] =
4779 EL_PLAYER_1, ACTION_MOVING, MV_BIT_UP,
4783 EL_PLAYER_1, ACTION_MOVING, MV_BIT_RIGHT,
4787 EL_PLAYER_1, ACTION_MOVING, MV_BIT_DOWN,
4791 EL_PLAYER_1, ACTION_MOVING, MV_BIT_LEFT,
4795 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_UP,
4799 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_RIGHT,
4803 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_DOWN,
4807 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_LEFT,
4811 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_UP,
4815 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_RIGHT,
4819 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_DOWN,
4823 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_LEFT,
4827 EL_PLAYER_2, ACTION_MOVING, MV_BIT_UP,
4831 EL_PLAYER_2, ACTION_MOVING, MV_BIT_RIGHT,
4835 EL_PLAYER_2, ACTION_MOVING, MV_BIT_DOWN,
4839 EL_PLAYER_2, ACTION_MOVING, MV_BIT_LEFT,
4843 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_UP,
4847 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_RIGHT,
4851 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_DOWN,
4855 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_LEFT,
4859 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_UP,
4863 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_RIGHT,
4867 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_DOWN,
4871 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_LEFT,
4875 EL_PLAYER_1, ACTION_DEFAULT, -1,
4879 EL_PLAYER_2, ACTION_DEFAULT, -1,
4888 int map_element_RND_to_EM(int element_rnd)
4890 static unsigned short mapping_RND_to_EM[NUM_FILE_ELEMENTS];
4891 static boolean mapping_initialized = FALSE;
4893 if (!mapping_initialized)
4897 /* return "Xalpha_quest" for all undefined elements in mapping array */
4898 for (i = 0; i < NUM_FILE_ELEMENTS; i++)
4899 mapping_RND_to_EM[i] = Xalpha_quest;
4901 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
4902 if (em_object_mapping_list[i].is_rnd_to_em_mapping)
4903 mapping_RND_to_EM[em_object_mapping_list[i].element_rnd] =
4904 em_object_mapping_list[i].element_em;
4906 mapping_initialized = TRUE;
4909 if (element_rnd >= 0 && element_rnd < NUM_FILE_ELEMENTS)
4910 return mapping_RND_to_EM[element_rnd];
4912 Error(ERR_WARN, "invalid RND level element %d", element_rnd);
4917 int map_element_EM_to_RND(int element_em)
4919 static unsigned short mapping_EM_to_RND[TILE_MAX];
4920 static boolean mapping_initialized = FALSE;
4922 if (!mapping_initialized)
4926 /* return "EL_UNKNOWN" for all undefined elements in mapping array */
4927 for (i = 0; i < TILE_MAX; i++)
4928 mapping_EM_to_RND[i] = EL_UNKNOWN;
4930 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
4931 mapping_EM_to_RND[em_object_mapping_list[i].element_em] =
4932 em_object_mapping_list[i].element_rnd;
4934 mapping_initialized = TRUE;
4937 if (element_em >= 0 && element_em < TILE_MAX)
4938 return mapping_EM_to_RND[element_em];
4940 Error(ERR_WARN, "invalid EM level element %d", element_em);
4947 int map_element_RND_to_EM(int element_rnd)
4949 static unsigned short mapping_RND_to_EM[NUM_FILE_ELEMENTS];
4950 static boolean mapping_initialized = FALSE;
4957 mapping_RND_to_EM_list[] =
4959 { Xblank, EL_EMPTY },
4960 { Xstone, EL_ROCK },
4962 { Xbug_n, EL_BUG_UP },
4963 { Xbug_e, EL_BUG_RIGHT },
4964 { Xbug_s, EL_BUG_DOWN },
4965 { Xbug_w, EL_BUG_LEFT },
4966 { Xtank_n, EL_SPACESHIP_UP },
4967 { Xtank_e, EL_SPACESHIP_RIGHT },
4968 { Xtank_s, EL_SPACESHIP_DOWN },
4969 { Xtank_w, EL_SPACESHIP_LEFT },
4970 { Xandroid, EL_EMC_ANDROID },
4971 { Xandroid_1_n, EL_EMC_ANDROID_UP },
4972 { Xandroid_1_e, EL_EMC_ANDROID_RIGHT },
4973 { Xandroid_1_w, EL_EMC_ANDROID_LEFT },
4974 { Xandroid_1_s, EL_EMC_ANDROID_DOWN },
4975 { Xspring, EL_SPRING },
4976 { Xeater_n, EL_YAMYAM },
4977 { Xalien, EL_ROBOT },
4978 { Xemerald, EL_EMERALD },
4979 { Xdiamond, EL_DIAMOND },
4980 { Xdrip_fall, EL_AMOEBA_DROP },
4982 { Xballoon, EL_BALLOON },
4983 { Xgrass, EL_EMC_GRASS },
4985 { Xacid_ne, EL_ACID_POOL_TOPRIGHT },
4986 { Xacid_se, EL_ACID_POOL_BOTTOMRIGHT },
4987 { Xacid_s, EL_ACID_POOL_BOTTOM },
4988 { Xacid_sw, EL_ACID_POOL_BOTTOMLEFT },
4989 { Xacid_nw, EL_ACID_POOL_TOPLEFT },
4990 { Xacid_1, EL_ACID },
4991 { Xball_1, EL_EMC_MAGIC_BALL },
4992 { Xgrow_ns, EL_EMC_GROW },
4993 { Xwonderwall, EL_MAGIC_WALL },
4994 { Xamoeba_1, EL_AMOEBA_WET },
4995 { Xdoor_1, EL_EM_GATE_1 },
4996 { Xdoor_2, EL_EM_GATE_2 },
4997 { Xdoor_3, EL_EM_GATE_3 },
4998 { Xdoor_4, EL_EM_GATE_4 },
4999 { Xdoor_5, EL_EMC_GATE_5 },
5000 { Xdoor_6, EL_EMC_GATE_6 },
5001 { Xdoor_7, EL_EMC_GATE_7 },
5002 { Xdoor_8, EL_EMC_GATE_8 },
5003 { Xkey_1, EL_EM_KEY_1 },
5004 { Xkey_2, EL_EM_KEY_2 },
5005 { Xkey_3, EL_EM_KEY_3 },
5006 { Xkey_4, EL_EM_KEY_4 },
5007 { Xkey_5, EL_EMC_KEY_5 },
5008 { Xkey_6, EL_EMC_KEY_6 },
5009 { Xkey_7, EL_EMC_KEY_7 },
5010 { Xkey_8, EL_EMC_KEY_8 },
5011 { Xwind_n, EL_BALLOON_SWITCH_UP },
5012 { Xwind_e, EL_BALLOON_SWITCH_RIGHT },
5013 { Xwind_s, EL_BALLOON_SWITCH_DOWN },
5014 { Xwind_w, EL_BALLOON_SWITCH_LEFT },
5015 { Xwind_nesw, EL_BALLOON_SWITCH_ANY },
5016 { Xwind_stop, EL_BALLOON_SWITCH_NONE },
5017 { Xexit, EL_EXIT_CLOSED },
5018 { Xexit_1, EL_EXIT_OPEN },
5019 { Xdynamite, EL_DYNAMITE },
5020 { Xdynamite_1, EL_DYNAMITE_ACTIVE },
5021 { Xbumper, EL_EMC_BUMPER },
5022 { Xwheel, EL_ROBOT_WHEEL },
5023 { Xswitch, EL_UNKNOWN },
5024 { Xsand, EL_QUICKSAND_EMPTY },
5025 { Xsand_stone, EL_QUICKSAND_FULL },
5026 { Xplant, EL_EMC_PLANT },
5027 { Xlenses, EL_EMC_LENSES },
5028 { Xmagnify, EL_EMC_MAGNIFIER },
5029 { Xdripper, EL_UNKNOWN },
5030 { Xfake_blank, EL_INVISIBLE_WALL },
5031 { Xfake_grass, EL_INVISIBLE_SAND },
5032 { Xfake_door_1, EL_EM_GATE_1_GRAY },
5033 { Xfake_door_2, EL_EM_GATE_2_GRAY },
5034 { Xfake_door_3, EL_EM_GATE_3_GRAY },
5035 { Xfake_door_4, EL_EM_GATE_4_GRAY },
5036 { Xfake_door_5, EL_EMC_GATE_5_GRAY },
5037 { Xfake_door_6, EL_EMC_GATE_6_GRAY },
5038 { Xfake_door_7, EL_EMC_GATE_7_GRAY },
5039 { Xfake_door_8, EL_EMC_GATE_8_GRAY },
5040 { Xsteel_1, EL_STEELWALL },
5041 { Xsteel_2, EL_UNKNOWN },
5042 { Xsteel_3, EL_EMC_STEELWALL_1 },
5043 { Xsteel_4, EL_UNKNOWN },
5044 { Xwall_1, EL_WALL },
5045 { Xwall_2, EL_UNKNOWN },
5046 { Xwall_3, EL_UNKNOWN },
5047 { Xwall_4, EL_UNKNOWN },
5048 { Xround_wall_1, EL_WALL_SLIPPERY },
5049 { Xround_wall_2, EL_UNKNOWN },
5050 { Xround_wall_3, EL_UNKNOWN },
5051 { Xround_wall_4, EL_UNKNOWN },
5052 { Xdecor_1, EL_UNKNOWN },
5053 { Xdecor_2, EL_EMC_WALL_6 },
5054 { Xdecor_3, EL_EMC_WALL_4 },
5055 { Xdecor_4, EL_EMC_WALL_5 },
5056 { Xdecor_5, EL_EMC_WALL_7 },
5057 { Xdecor_6, EL_EMC_WALL_8 },
5058 { Xdecor_7, EL_UNKNOWN },
5059 { Xdecor_8, EL_EMC_WALL_1 },
5060 { Xdecor_9, EL_EMC_WALL_2 },
5061 { Xdecor_10, EL_EMC_WALL_3 },
5062 { Xdecor_11, EL_UNKNOWN },
5063 { Xdecor_12, EL_UNKNOWN },
5064 { Xalpha_0, EL_CHAR('0') },
5065 { Xalpha_1, EL_CHAR('1') },
5066 { Xalpha_2, EL_CHAR('2') },
5067 { Xalpha_3, EL_CHAR('3') },
5068 { Xalpha_4, EL_CHAR('4') },
5069 { Xalpha_5, EL_CHAR('5') },
5070 { Xalpha_6, EL_CHAR('6') },
5071 { Xalpha_7, EL_CHAR('7') },
5072 { Xalpha_8, EL_CHAR('8') },
5073 { Xalpha_9, EL_CHAR('9') },
5074 { Xalpha_excla, EL_CHAR('!') },
5075 { Xalpha_quote, EL_CHAR('"') },
5076 { Xalpha_comma, EL_CHAR(',') },
5077 { Xalpha_minus, EL_CHAR('-') },
5078 { Xalpha_perio, EL_CHAR('.') },
5079 { Xalpha_colon, EL_CHAR(':') },
5080 { Xalpha_quest, EL_CHAR('?') },
5081 { Xalpha_a, EL_CHAR('A') },
5082 { Xalpha_b, EL_CHAR('B') },
5083 { Xalpha_c, EL_CHAR('C') },
5084 { Xalpha_d, EL_CHAR('D') },
5085 { Xalpha_e, EL_CHAR('E') },
5086 { Xalpha_f, EL_CHAR('F') },
5087 { Xalpha_g, EL_CHAR('G') },
5088 { Xalpha_h, EL_CHAR('H') },
5089 { Xalpha_i, EL_CHAR('I') },
5090 { Xalpha_j, EL_CHAR('J') },
5091 { Xalpha_k, EL_CHAR('K') },
5092 { Xalpha_l, EL_CHAR('L') },
5093 { Xalpha_m, EL_CHAR('M') },
5094 { Xalpha_n, EL_CHAR('N') },
5095 { Xalpha_o, EL_CHAR('O') },
5096 { Xalpha_p, EL_CHAR('P') },
5097 { Xalpha_q, EL_CHAR('Q') },
5098 { Xalpha_r, EL_CHAR('R') },
5099 { Xalpha_s, EL_CHAR('S') },
5100 { Xalpha_t, EL_CHAR('T') },
5101 { Xalpha_u, EL_CHAR('U') },
5102 { Xalpha_v, EL_CHAR('V') },
5103 { Xalpha_w, EL_CHAR('W') },
5104 { Xalpha_x, EL_CHAR('X') },
5105 { Xalpha_y, EL_CHAR('Y') },
5106 { Xalpha_z, EL_CHAR('Z') },
5107 { Xalpha_arrow_e, EL_CHAR('>') },
5108 { Xalpha_arrow_w, EL_CHAR('<') },
5109 { Xalpha_copyr, EL_CHAR('©') },
5111 { Zplayer, EL_PLAYER_1 },
5112 { Zplayer, EL_PLAYER_2 },
5113 { Zplayer, EL_PLAYER_3 },
5114 { Zplayer, EL_PLAYER_4 },
5116 { ZBORDER, EL_EMC_LEVEL_BORDER },
5121 if (!mapping_initialized)
5125 /* return "Xalpha_quest" for all undefined elements in mapping array */
5126 for (i = 0; i < NUM_FILE_ELEMENTS; i++)
5127 mapping_RND_to_EM[i] = Xalpha_quest;
5129 for (i = 0; mapping_RND_to_EM_list[i].element_rnd != -1; i++)
5130 mapping_RND_to_EM[mapping_RND_to_EM_list[i].element_rnd] =
5131 mapping_RND_to_EM_list[i].element_em;
5133 mapping_initialized = TRUE;
5136 if (element_rnd >= 0 && element_rnd < NUM_FILE_ELEMENTS)
5137 return mapping_RND_to_EM[element_rnd];
5139 Error(ERR_WARN, "invalid RND level element %d", element_rnd);
5144 int map_element_EM_to_RND(int element_em)
5146 static unsigned short mapping_EM_to_RND[TILE_MAX];
5147 static boolean mapping_initialized = FALSE;
5154 em_object_mapping_list[] =
5156 { Xblank, EL_EMPTY },
5157 { Yacid_splash_eB, EL_EMPTY },
5158 { Yacid_splash_wB, EL_EMPTY },
5160 #ifdef EM_ENGINE_BAD_ROLL
5161 { Xstone_force_e, EL_ROCK },
5162 { Xstone_force_w, EL_ROCK },
5163 { Xnut_force_e, EL_NUT },
5164 { Xnut_force_w, EL_NUT },
5165 { Xspring_force_e, EL_SPRING },
5166 { Xspring_force_w, EL_SPRING },
5167 { Xemerald_force_e, EL_EMERALD },
5168 { Xemerald_force_w, EL_EMERALD },
5169 { Xdiamond_force_e, EL_DIAMOND },
5170 { Xdiamond_force_w, EL_DIAMOND },
5171 { Xbomb_force_e, EL_BOMB },
5172 { Xbomb_force_w, EL_BOMB },
5175 { Xstone, EL_ROCK },
5176 { Xstone_pause, EL_ROCK },
5177 { Xstone_fall, EL_ROCK },
5178 { Ystone_s, EL_ROCK },
5179 { Ystone_sB, EL_ROCK },
5180 { Ystone_e, EL_ROCK },
5181 { Ystone_eB, EL_ROCK },
5182 { Ystone_w, EL_ROCK },
5183 { Ystone_wB, EL_ROCK },
5185 { Xnut_pause, EL_NUT },
5186 { Xnut_fall, EL_NUT },
5188 { Ynut_sB, EL_NUT },
5190 { Ynut_eB, EL_NUT },
5192 { Ynut_wB, EL_NUT },
5193 { Xbug_n, EL_BUG_UP },
5194 { Xbug_e, EL_BUG_RIGHT },
5195 { Xbug_s, EL_BUG_DOWN },
5196 { Xbug_w, EL_BUG_LEFT },
5197 { Xbug_gon, EL_BUG_UP },
5198 { Xbug_goe, EL_BUG_RIGHT },
5199 { Xbug_gos, EL_BUG_DOWN },
5200 { Xbug_gow, EL_BUG_LEFT },
5201 { Ybug_n, EL_BUG_UP },
5202 { Ybug_nB, EL_BUG_UP },
5203 { Ybug_e, EL_BUG_RIGHT },
5204 { Ybug_eB, EL_BUG_RIGHT },
5205 { Ybug_s, EL_BUG_DOWN },
5206 { Ybug_sB, EL_BUG_DOWN },
5207 { Ybug_w, EL_BUG_LEFT },
5208 { Ybug_wB, EL_BUG_LEFT },
5209 { Ybug_w_n, EL_BUG_UP },
5210 { Ybug_n_e, EL_BUG_RIGHT },
5211 { Ybug_e_s, EL_BUG_DOWN },
5212 { Ybug_s_w, EL_BUG_LEFT },
5213 { Ybug_e_n, EL_BUG_UP },
5214 { Ybug_s_e, EL_BUG_RIGHT },
5215 { Ybug_w_s, EL_BUG_DOWN },
5216 { Ybug_n_w, EL_BUG_LEFT },
5217 { Ybug_stone, EL_ROCK },
5218 { Ybug_spring, EL_SPRING },
5219 { Xtank_n, EL_SPACESHIP_UP },
5220 { Xtank_e, EL_SPACESHIP_RIGHT },
5221 { Xtank_s, EL_SPACESHIP_DOWN },
5222 { Xtank_w, EL_SPACESHIP_LEFT },
5223 { Xtank_gon, EL_SPACESHIP_UP },
5224 { Xtank_goe, EL_SPACESHIP_RIGHT },
5225 { Xtank_gos, EL_SPACESHIP_DOWN },
5226 { Xtank_gow, EL_SPACESHIP_LEFT },
5227 { Ytank_n, EL_SPACESHIP_UP },
5228 { Ytank_nB, EL_SPACESHIP_UP },
5229 { Ytank_e, EL_SPACESHIP_RIGHT },
5230 { Ytank_eB, EL_SPACESHIP_RIGHT },
5231 { Ytank_s, EL_SPACESHIP_DOWN },
5232 { Ytank_sB, EL_SPACESHIP_DOWN },
5233 { Ytank_w, EL_SPACESHIP_LEFT },
5234 { Ytank_wB, EL_SPACESHIP_LEFT },
5235 { Ytank_w_n, EL_SPACESHIP_UP },
5236 { Ytank_n_e, EL_SPACESHIP_RIGHT },
5237 { Ytank_e_s, EL_SPACESHIP_DOWN },
5238 { Ytank_s_w, EL_SPACESHIP_LEFT },
5239 { Ytank_e_n, EL_SPACESHIP_UP },
5240 { Ytank_s_e, EL_SPACESHIP_RIGHT },
5241 { Ytank_w_s, EL_SPACESHIP_DOWN },
5242 { Ytank_n_w, EL_SPACESHIP_LEFT },
5243 { Ytank_stone, EL_ROCK },
5244 { Ytank_spring, EL_SPRING },
5245 { Xandroid, EL_EMC_ANDROID },
5246 { Xandroid_1_n, EL_EMC_ANDROID_UP },
5247 { Xandroid_2_n, EL_EMC_ANDROID_UP },
5248 { Xandroid_1_e, EL_EMC_ANDROID_RIGHT },
5249 { Xandroid_2_e, EL_EMC_ANDROID_RIGHT },
5250 { Xandroid_1_w, EL_EMC_ANDROID_LEFT },
5251 { Xandroid_2_w, EL_EMC_ANDROID_LEFT },
5252 { Xandroid_1_s, EL_EMC_ANDROID_DOWN },
5253 { Xandroid_2_s, EL_EMC_ANDROID_DOWN },
5254 { Yandroid_n, EL_EMC_ANDROID_UP },
5255 { Yandroid_nB, EL_EMC_ANDROID_UP },
5256 { Yandroid_ne, EL_EMC_ANDROID_RIGHT_UP },
5257 { Yandroid_neB, EL_EMC_ANDROID_RIGHT_UP },
5258 { Yandroid_e, EL_EMC_ANDROID_RIGHT },
5259 { Yandroid_eB, EL_EMC_ANDROID_RIGHT },
5260 { Yandroid_se, EL_EMC_ANDROID_RIGHT_DOWN },
5261 { Yandroid_seB, EL_EMC_ANDROID_RIGHT_DOWN },
5262 { Yandroid_s, EL_EMC_ANDROID_DOWN },
5263 { Yandroid_sB, EL_EMC_ANDROID_DOWN },
5264 { Yandroid_sw, EL_EMC_ANDROID_LEFT_DOWN },
5265 { Yandroid_swB, EL_EMC_ANDROID_LEFT_DOWN },
5266 { Yandroid_w, EL_EMC_ANDROID_LEFT },
5267 { Yandroid_wB, EL_EMC_ANDROID_LEFT },
5268 { Yandroid_nw, EL_EMC_ANDROID_LEFT_UP },
5269 { Yandroid_nwB, EL_EMC_ANDROID_LEFT_UP },
5270 { Xspring, EL_SPRING },
5271 { Xspring_pause, EL_SPRING },
5272 { Xspring_e, EL_SPRING },
5273 { Xspring_w, EL_SPRING },
5274 { Xspring_fall, EL_SPRING },
5275 { Yspring_s, EL_SPRING },
5276 { Yspring_sB, EL_SPRING },
5277 { Yspring_e, EL_SPRING },
5278 { Yspring_eB, EL_SPRING },
5279 { Yspring_w, EL_SPRING },
5280 { Yspring_wB, EL_SPRING },
5281 { Yspring_kill_e, EL_SPRING },
5282 { Yspring_kill_eB, EL_SPRING },
5283 { Yspring_kill_w, EL_SPRING },
5284 { Yspring_kill_wB, EL_SPRING },
5285 { Xeater_n, EL_YAMYAM },
5286 { Xeater_e, EL_YAMYAM },
5287 { Xeater_w, EL_YAMYAM },
5288 { Xeater_s, EL_YAMYAM },
5289 { Yeater_n, EL_YAMYAM },
5290 { Yeater_nB, EL_YAMYAM },
5291 { Yeater_e, EL_YAMYAM },
5292 { Yeater_eB, EL_YAMYAM },
5293 { Yeater_s, EL_YAMYAM },
5294 { Yeater_sB, EL_YAMYAM },
5295 { Yeater_w, EL_YAMYAM },
5296 { Yeater_wB, EL_YAMYAM },
5297 { Yeater_stone, EL_ROCK },
5298 { Yeater_spring, EL_SPRING },
5299 { Xalien, EL_ROBOT },
5300 { Xalien_pause, EL_ROBOT },
5301 { Yalien_n, EL_ROBOT },
5302 { Yalien_nB, EL_ROBOT },
5303 { Yalien_e, EL_ROBOT },
5304 { Yalien_eB, EL_ROBOT },
5305 { Yalien_s, EL_ROBOT },
5306 { Yalien_sB, EL_ROBOT },
5307 { Yalien_w, EL_ROBOT },
5308 { Yalien_wB, EL_ROBOT },
5309 { Yalien_stone, EL_ROCK },
5310 { Yalien_spring, EL_SPRING },
5311 { Xemerald, EL_EMERALD },
5312 { Xemerald_pause, EL_EMERALD },
5313 { Xemerald_fall, EL_EMERALD },
5314 { Xemerald_shine, EL_EMERALD },
5315 { Yemerald_s, EL_EMERALD },
5316 { Yemerald_sB, EL_EMERALD },
5317 { Yemerald_e, EL_EMERALD },
5318 { Yemerald_eB, EL_EMERALD },
5319 { Yemerald_w, EL_EMERALD },
5320 { Yemerald_wB, EL_EMERALD },
5321 { Yemerald_eat, EL_EMERALD },
5322 { Yemerald_stone, EL_ROCK },
5323 { Xdiamond, EL_DIAMOND },
5324 { Xdiamond_pause, EL_DIAMOND },
5325 { Xdiamond_fall, EL_DIAMOND },
5326 { Xdiamond_shine, EL_DIAMOND },
5327 { Ydiamond_s, EL_DIAMOND },
5328 { Ydiamond_sB, EL_DIAMOND },
5329 { Ydiamond_e, EL_DIAMOND },
5330 { Ydiamond_eB, EL_DIAMOND },
5331 { Ydiamond_w, EL_DIAMOND },
5332 { Ydiamond_wB, EL_DIAMOND },
5333 { Ydiamond_eat, EL_DIAMOND },
5334 { Ydiamond_stone, EL_ROCK },
5335 { Xdrip_fall, EL_AMOEBA_DROP },
5336 { Xdrip_stretch, EL_AMOEBA_DROP },
5337 { Xdrip_stretchB, EL_AMOEBA_DROP },
5338 { Xdrip_eat, EL_AMOEBA_DROP },
5339 { Ydrip_s1, EL_AMOEBA_DROP },
5340 { Ydrip_s1B, EL_AMOEBA_DROP },
5341 { Ydrip_s2, EL_AMOEBA_DROP },
5342 { Ydrip_s2B, EL_AMOEBA_DROP },
5344 { Xbomb_pause, EL_BOMB },
5345 { Xbomb_fall, EL_BOMB },
5346 { Ybomb_s, EL_BOMB },
5347 { Ybomb_sB, EL_BOMB },
5348 { Ybomb_e, EL_BOMB },
5349 { Ybomb_eB, EL_BOMB },
5350 { Ybomb_w, EL_BOMB },
5351 { Ybomb_wB, EL_BOMB },
5352 { Ybomb_eat, EL_BOMB },
5353 { Xballoon, EL_BALLOON },
5354 { Yballoon_n, EL_BALLOON },
5355 { Yballoon_nB, EL_BALLOON },
5356 { Yballoon_e, EL_BALLOON },
5357 { Yballoon_eB, EL_BALLOON },
5358 { Yballoon_s, EL_BALLOON },
5359 { Yballoon_sB, EL_BALLOON },
5360 { Yballoon_w, EL_BALLOON },
5361 { Yballoon_wB, EL_BALLOON },
5362 { Xgrass, EL_SAND },
5363 { Ygrass_nB, EL_SAND },
5364 { Ygrass_eB, EL_SAND },
5365 { Ygrass_sB, EL_SAND },
5366 { Ygrass_wB, EL_SAND },
5368 { Ydirt_nB, EL_SAND },
5369 { Ydirt_eB, EL_SAND },
5370 { Ydirt_sB, EL_SAND },
5371 { Ydirt_wB, EL_SAND },
5372 { Xacid_ne, EL_ACID_POOL_TOPRIGHT },
5373 { Xacid_se, EL_ACID_POOL_BOTTOMRIGHT },
5374 { Xacid_s, EL_ACID_POOL_BOTTOM },
5375 { Xacid_sw, EL_ACID_POOL_BOTTOMLEFT },
5376 { Xacid_nw, EL_ACID_POOL_TOPLEFT },
5377 { Xacid_1, EL_ACID },
5378 { Xacid_2, EL_ACID },
5379 { Xacid_3, EL_ACID },
5380 { Xacid_4, EL_ACID },
5381 { Xacid_5, EL_ACID },
5382 { Xacid_6, EL_ACID },
5383 { Xacid_7, EL_ACID },
5384 { Xacid_8, EL_ACID },
5385 { Xball_1, EL_EMC_MAGIC_BALL },
5386 { Xball_1B, EL_EMC_MAGIC_BALL },
5387 { Xball_2, EL_EMC_MAGIC_BALL },
5388 { Xball_2B, EL_EMC_MAGIC_BALL },
5389 { Yball_eat, EL_EMC_MAGIC_BALL },
5390 { Xgrow_ns, EL_EMC_GROW },
5391 { Ygrow_ns_eat, EL_EMC_GROW },
5392 { Xgrow_ew, EL_EMC_GROW },
5393 { Ygrow_ew_eat, EL_EMC_GROW },
5394 { Xwonderwall, EL_MAGIC_WALL },
5395 { XwonderwallB, EL_MAGIC_WALL },
5396 { Xamoeba_1, EL_AMOEBA_WET },
5397 { Xamoeba_2, EL_AMOEBA_WET },
5398 { Xamoeba_3, EL_AMOEBA_WET },
5399 { Xamoeba_4, EL_AMOEBA_WET },
5400 { Xamoeba_5, EL_AMOEBA_WET },
5401 { Xamoeba_6, EL_AMOEBA_WET },
5402 { Xamoeba_7, EL_AMOEBA_WET },
5403 { Xamoeba_8, EL_AMOEBA_WET },
5404 { Xdoor_1, EL_EM_GATE_1 },
5405 { Xdoor_2, EL_EM_GATE_2 },
5406 { Xdoor_3, EL_EM_GATE_3 },
5407 { Xdoor_4, EL_EM_GATE_4 },
5408 { Xdoor_5, EL_EMC_GATE_5 },
5409 { Xdoor_6, EL_EMC_GATE_6 },
5410 { Xdoor_7, EL_EMC_GATE_7 },
5411 { Xdoor_8, EL_EMC_GATE_8 },
5412 { Xkey_1, EL_EM_KEY_1 },
5413 { Xkey_2, EL_EM_KEY_2 },
5414 { Xkey_3, EL_EM_KEY_3 },
5415 { Xkey_4, EL_EM_KEY_4 },
5416 { Xkey_5, EL_EMC_KEY_5 },
5417 { Xkey_6, EL_EMC_KEY_6 },
5418 { Xkey_7, EL_EMC_KEY_7 },
5419 { Xkey_8, EL_EMC_KEY_8 },
5420 { Xwind_n, EL_BALLOON_SWITCH_UP },
5421 { Xwind_e, EL_BALLOON_SWITCH_RIGHT },
5422 { Xwind_s, EL_BALLOON_SWITCH_DOWN },
5423 { Xwind_w, EL_BALLOON_SWITCH_LEFT },
5424 { Xwind_nesw, EL_BALLOON_SWITCH_ANY },
5425 { Xwind_stop, EL_BALLOON_SWITCH_NONE },
5426 { Xexit, EL_EXIT_CLOSED },
5427 { Xexit_1, EL_EXIT_OPEN },
5428 { Xexit_2, EL_EXIT_OPEN },
5429 { Xexit_3, EL_EXIT_OPEN },
5430 { Xdynamite, EL_DYNAMITE },
5431 { Ydynamite_eat, EL_DYNAMITE },
5432 { Xdynamite_1, EL_DYNAMITE_ACTIVE },
5433 { Xdynamite_2, EL_DYNAMITE_ACTIVE },
5434 { Xdynamite_3, EL_DYNAMITE_ACTIVE },
5435 { Xdynamite_4, EL_DYNAMITE_ACTIVE },
5436 { Xbumper, EL_EMC_BUMPER },
5437 { XbumperB, EL_EMC_BUMPER },
5438 { Xwheel, EL_ROBOT_WHEEL },
5439 { XwheelB, EL_ROBOT_WHEEL },
5440 { Xswitch, EL_UNKNOWN },
5441 { XswitchB, EL_UNKNOWN },
5442 { Xsand, EL_QUICKSAND_EMPTY },
5443 { Xsand_stone, EL_QUICKSAND_FULL },
5444 { Xsand_stonein_1, EL_QUICKSAND_FULL },
5445 { Xsand_stonein_2, EL_QUICKSAND_FULL },
5446 { Xsand_stonein_3, EL_QUICKSAND_FULL },
5447 { Xsand_stonein_4, EL_QUICKSAND_FULL },
5448 { Xsand_stonesand_1, EL_QUICKSAND_FULL },
5449 { Xsand_stonesand_2, EL_QUICKSAND_FULL },
5450 { Xsand_stonesand_3, EL_QUICKSAND_FULL },
5451 { Xsand_stonesand_4, EL_QUICKSAND_FULL },
5452 { Xsand_stoneout_1, EL_QUICKSAND_FULL },
5453 { Xsand_stoneout_2, EL_QUICKSAND_FULL },
5454 { Xsand_sandstone_1, EL_QUICKSAND_FULL },
5455 { Xsand_sandstone_2, EL_QUICKSAND_FULL },
5456 { Xsand_sandstone_3, EL_QUICKSAND_FULL },
5457 { Xsand_sandstone_4, EL_QUICKSAND_FULL },
5458 { Xplant, EL_EMC_PLANT },
5459 { Yplant, EL_EMC_PLANT },
5460 { Xlenses, EL_EMC_LENSES },
5461 { Xmagnify, EL_EMC_MAGNIFIER },
5462 { Xdripper, EL_UNKNOWN },
5463 { XdripperB, EL_UNKNOWN },
5464 { Xfake_blank, EL_INVISIBLE_WALL },
5465 { Xfake_blankB, EL_INVISIBLE_WALL },
5466 { Xfake_grass, EL_INVISIBLE_SAND },
5467 { Xfake_grassB, EL_INVISIBLE_SAND },
5468 { Xfake_door_1, EL_EM_GATE_1_GRAY },
5469 { Xfake_door_2, EL_EM_GATE_2_GRAY },
5470 { Xfake_door_3, EL_EM_GATE_3_GRAY },
5471 { Xfake_door_4, EL_EM_GATE_4_GRAY },
5472 { Xfake_door_5, EL_EMC_GATE_5_GRAY },
5473 { Xfake_door_6, EL_EMC_GATE_6_GRAY },
5474 { Xfake_door_7, EL_EMC_GATE_7_GRAY },
5475 { Xfake_door_8, EL_EMC_GATE_8_GRAY },
5476 { Xsteel_1, EL_STEELWALL },
5477 { Xsteel_2, EL_UNKNOWN },
5478 { Xsteel_3, EL_EMC_STEELWALL_1 },
5479 { Xsteel_4, EL_UNKNOWN },
5480 { Xwall_1, EL_WALL },
5481 { Xwall_2, EL_UNKNOWN },
5482 { Xwall_3, EL_UNKNOWN },
5483 { Xwall_4, EL_UNKNOWN },
5484 { Xround_wall_1, EL_WALL_SLIPPERY },
5485 { Xround_wall_2, EL_UNKNOWN },
5486 { Xround_wall_3, EL_UNKNOWN },
5487 { Xround_wall_4, EL_UNKNOWN },
5488 { Xdecor_1, EL_UNKNOWN },
5489 { Xdecor_2, EL_EMC_WALL_6 },
5490 { Xdecor_3, EL_EMC_WALL_4 },
5491 { Xdecor_4, EL_EMC_WALL_5 },
5492 { Xdecor_5, EL_EMC_WALL_7 },
5493 { Xdecor_6, EL_EMC_WALL_8 },
5494 { Xdecor_7, EL_UNKNOWN },
5495 { Xdecor_8, EL_EMC_WALL_1 },
5496 { Xdecor_9, EL_EMC_WALL_2 },
5497 { Xdecor_10, EL_EMC_WALL_3 },
5498 { Xdecor_11, EL_UNKNOWN },
5499 { Xdecor_12, EL_UNKNOWN },
5500 { Xalpha_0, EL_CHAR('0') },
5501 { Xalpha_1, EL_CHAR('1') },
5502 { Xalpha_2, EL_CHAR('2') },
5503 { Xalpha_3, EL_CHAR('3') },
5504 { Xalpha_4, EL_CHAR('4') },
5505 { Xalpha_5, EL_CHAR('5') },
5506 { Xalpha_6, EL_CHAR('6') },
5507 { Xalpha_7, EL_CHAR('7') },
5508 { Xalpha_8, EL_CHAR('8') },
5509 { Xalpha_9, EL_CHAR('9') },
5510 { Xalpha_excla, EL_CHAR('!') },
5511 { Xalpha_quote, EL_CHAR('"') },
5512 { Xalpha_comma, EL_CHAR(',') },
5513 { Xalpha_minus, EL_CHAR('-') },
5514 { Xalpha_perio, EL_CHAR('.') },
5515 { Xalpha_colon, EL_CHAR(':') },
5516 { Xalpha_quest, EL_CHAR('?') },
5517 { Xalpha_a, EL_CHAR('A') },
5518 { Xalpha_b, EL_CHAR('B') },
5519 { Xalpha_c, EL_CHAR('C') },
5520 { Xalpha_d, EL_CHAR('D') },
5521 { Xalpha_e, EL_CHAR('E') },
5522 { Xalpha_f, EL_CHAR('F') },
5523 { Xalpha_g, EL_CHAR('G') },
5524 { Xalpha_h, EL_CHAR('H') },
5525 { Xalpha_i, EL_CHAR('I') },
5526 { Xalpha_j, EL_CHAR('J') },
5527 { Xalpha_k, EL_CHAR('K') },
5528 { Xalpha_l, EL_CHAR('L') },
5529 { Xalpha_m, EL_CHAR('M') },
5530 { Xalpha_n, EL_CHAR('N') },
5531 { Xalpha_o, EL_CHAR('O') },
5532 { Xalpha_p, EL_CHAR('P') },
5533 { Xalpha_q, EL_CHAR('Q') },
5534 { Xalpha_r, EL_CHAR('R') },
5535 { Xalpha_s, EL_CHAR('S') },
5536 { Xalpha_t, EL_CHAR('T') },
5537 { Xalpha_u, EL_CHAR('U') },
5538 { Xalpha_v, EL_CHAR('V') },
5539 { Xalpha_w, EL_CHAR('W') },
5540 { Xalpha_x, EL_CHAR('X') },
5541 { Xalpha_y, EL_CHAR('Y') },
5542 { Xalpha_z, EL_CHAR('Z') },
5543 { Xalpha_arrow_e, EL_CHAR('>') },
5544 { Xalpha_arrow_w, EL_CHAR('<') },
5545 { Xalpha_copyr, EL_CHAR('©') },
5547 { Zplayer, EL_PLAYER_1 },
5549 { ZBORDER, EL_EMC_LEVEL_BORDER },
5554 if (!mapping_initialized)
5558 /* return "EL_UNKNOWN" for all undefined elements in mapping array */
5559 for (i = 0; i < TILE_MAX; i++)
5560 mapping_EM_to_RND[i] = EL_UNKNOWN;
5562 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
5563 mapping_EM_to_RND[em_object_mapping_list[i].element_em] =
5564 em_object_mapping_list[i].element_rnd;
5566 mapping_initialized = TRUE;
5569 if (element_em >= 0 && element_em < TILE_MAX)
5570 return mapping_EM_to_RND[element_em];
5572 Error(ERR_WARN, "invalid EM level element %d", element_em);
5579 int get_next_element(int element)
5583 case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL;
5584 case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY;
5585 case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL;
5586 case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_ACTIVE;
5587 case EL_BD_MAGIC_WALL_FILLING: return EL_BD_MAGIC_WALL_FULL;
5588 case EL_BD_MAGIC_WALL_EMPTYING: return EL_BD_MAGIC_WALL_ACTIVE;
5589 case EL_AMOEBA_DROPPING: return EL_AMOEBA_WET;
5591 default: return element;
5596 int el_act_dir2img(int element, int action, int direction)
5598 element = GFX_ELEMENT(element);
5600 if (direction == MV_NO_MOVING)
5601 return element_info[element].graphic[action];
5603 direction = MV_DIR_BIT(direction);
5605 return element_info[element].direction_graphic[action][direction];
5608 int el_act_dir2img(int element, int action, int direction)
5610 element = GFX_ELEMENT(element);
5611 direction = MV_DIR_BIT(direction); /* default: MV_NO_MOVING => MV_DOWN */
5613 /* direction_graphic[][] == graphic[] for undefined direction graphics */
5614 return element_info[element].direction_graphic[action][direction];
5619 static int el_act_dir2crm(int element, int action, int direction)
5621 element = GFX_ELEMENT(element);
5623 if (direction == MV_NO_MOVING)
5624 return element_info[element].crumbled[action];
5626 direction = MV_DIR_BIT(direction);
5628 return element_info[element].direction_crumbled[action][direction];
5631 static int el_act_dir2crm(int element, int action, int direction)
5633 element = GFX_ELEMENT(element);
5634 direction = MV_DIR_BIT(direction); /* default: MV_NO_MOVING => MV_DOWN */
5636 /* direction_graphic[][] == graphic[] for undefined direction graphics */
5637 return element_info[element].direction_crumbled[action][direction];
5641 int el_act2img(int element, int action)
5643 element = GFX_ELEMENT(element);
5645 return element_info[element].graphic[action];
5648 int el_act2crm(int element, int action)
5650 element = GFX_ELEMENT(element);
5652 return element_info[element].crumbled[action];
5655 int el_dir2img(int element, int direction)
5657 element = GFX_ELEMENT(element);
5659 return el_act_dir2img(element, ACTION_DEFAULT, direction);
5662 int el2baseimg(int element)
5664 return element_info[element].graphic[ACTION_DEFAULT];
5667 int el2img(int element)
5669 element = GFX_ELEMENT(element);
5671 return element_info[element].graphic[ACTION_DEFAULT];
5674 int el2edimg(int element)
5676 element = GFX_ELEMENT(element);
5678 return element_info[element].special_graphic[GFX_SPECIAL_ARG_EDITOR];
5681 int el2preimg(int element)
5683 element = GFX_ELEMENT(element);
5685 return element_info[element].special_graphic[GFX_SPECIAL_ARG_PREVIEW];
5688 int getGameFrameDelay_EM(int native_em_game_frame_delay)
5690 int game_frame_delay_value;
5692 game_frame_delay_value =
5693 (tape.playing && tape.fast_forward ? FfwdFrameDelay :
5694 GameFrameDelay == GAME_FRAME_DELAY ? native_em_game_frame_delay :
5697 if (tape.playing && tape.warp_forward && !tape.pausing)
5698 game_frame_delay_value = 0;
5700 return game_frame_delay_value;
5703 unsigned int InitRND(long seed)
5705 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
5706 return InitEngineRND_EM(seed);
5708 return InitEngineRND(seed);
5711 #define DEBUG_EM_GFX 0
5713 void InitGraphicInfo_EM(void)
5715 struct Mapping_EM_to_RND_object object_mapping[TILE_MAX];
5716 struct Mapping_EM_to_RND_player player_mapping[2][SPR_MAX];
5720 if (graphic_info_em_object[0][0].bitmap == NULL)
5722 /* EM graphics not yet initialized in em_open_all() */
5728 /* always start with reliable default values */
5729 for (i = 0; i < TILE_MAX; i++)
5731 object_mapping[i].element_rnd = EL_UNKNOWN;
5732 object_mapping[i].is_backside = FALSE;
5733 object_mapping[i].action = ACTION_DEFAULT;
5734 object_mapping[i].direction = MV_NO_MOVING;
5737 /* always start with reliable default values */
5738 for (p = 0; p < 2; p++)
5740 for (i = 0; i < SPR_MAX; i++)
5742 player_mapping[p][i].element_rnd = EL_UNKNOWN;
5743 player_mapping[p][i].action = ACTION_DEFAULT;
5744 player_mapping[p][i].direction = MV_NO_MOVING;
5748 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
5750 int e = em_object_mapping_list[i].element_em;
5752 object_mapping[e].element_rnd = em_object_mapping_list[i].element_rnd;
5753 object_mapping[e].is_backside = em_object_mapping_list[i].is_backside;
5755 if (em_object_mapping_list[i].action != -1)
5756 object_mapping[e].action = em_object_mapping_list[i].action;
5758 if (em_object_mapping_list[i].direction != -1)
5759 object_mapping[e].direction = (1 << em_object_mapping_list[i].direction);
5762 for (i = 0; em_player_mapping_list[i].action_em != -1; i++)
5764 int a = em_player_mapping_list[i].action_em;
5765 int p = em_player_mapping_list[i].player_nr;
5767 player_mapping[p][a].element_rnd = em_player_mapping_list[i].element_rnd;
5769 if (em_player_mapping_list[i].action != -1)
5770 player_mapping[p][a].action = em_player_mapping_list[i].action;
5772 if (em_player_mapping_list[i].direction != -1)
5773 player_mapping[p][a].direction =
5774 (1 << em_player_mapping_list[i].direction);
5777 for (i = 0; i < TILE_MAX; i++)
5779 int element = object_mapping[i].element_rnd;
5780 int action = object_mapping[i].action;
5781 int direction = object_mapping[i].direction;
5782 boolean is_backside = object_mapping[i].is_backside;
5783 boolean action_removing = (action == ACTION_DIGGING ||
5784 action == ACTION_SNAPPING ||
5785 action == ACTION_COLLECTING);
5786 boolean action_exploding = ((action == ACTION_EXPLODING ||
5787 action == ACTION_SMASHED_BY_ROCK ||
5788 action == ACTION_SMASHED_BY_SPRING) &&
5789 element != EL_DIAMOND);
5790 boolean action_active = (action == ACTION_ACTIVE);
5791 boolean action_other = (action == ACTION_OTHER);
5793 for (j = 0; j < 8; j++)
5795 int effective_element = (j > 5 && i == Yacid_splash_eB ? EL_EMPTY :
5796 j > 5 && i == Yacid_splash_wB ? EL_EMPTY :
5798 i == Xdrip_stretch ? element :
5799 i == Xdrip_stretchB ? element :
5800 i == Ydrip_s1 ? element :
5801 i == Ydrip_s1B ? element :
5802 i == Xball_1B ? element :
5803 i == Xball_2 ? element :
5804 i == Xball_2B ? element :
5805 i == Yball_eat ? element :
5806 i == Ykey_1_eat ? element :
5807 i == Ykey_2_eat ? element :
5808 i == Ykey_3_eat ? element :
5809 i == Ykey_4_eat ? element :
5810 i == Ykey_5_eat ? element :
5811 i == Ykey_6_eat ? element :
5812 i == Ykey_7_eat ? element :
5813 i == Ykey_8_eat ? element :
5814 i == Ylenses_eat ? element :
5815 i == Ymagnify_eat ? element :
5816 i == Ygrass_eat ? element :
5817 i == Ydirt_eat ? element :
5818 i == Yspring_kill_e ? EL_SPRING :
5819 i == Yspring_kill_w ? EL_SPRING :
5820 i == Yemerald_stone ? EL_EMERALD :
5821 i == Ydiamond_stone ? EL_ROCK :
5822 i == Xsand_stonein_4 ? EL_EMPTY :
5823 i == Xsand_stoneout_2 ? EL_ROCK :
5824 is_backside ? EL_EMPTY :
5825 action_removing ? EL_EMPTY :
5827 int effective_action = (j < 7 ? action :
5828 i == Xdrip_stretch ? action :
5829 i == Xdrip_stretchB ? action :
5830 i == Ydrip_s1 ? action :
5831 i == Ydrip_s1B ? action :
5832 i == Xball_1B ? action :
5833 i == Xball_2 ? action :
5834 i == Xball_2B ? action :
5835 i == Yball_eat ? action :
5836 i == Ykey_1_eat ? action :
5837 i == Ykey_2_eat ? action :
5838 i == Ykey_3_eat ? action :
5839 i == Ykey_4_eat ? action :
5840 i == Ykey_5_eat ? action :
5841 i == Ykey_6_eat ? action :
5842 i == Ykey_7_eat ? action :
5843 i == Ykey_8_eat ? action :
5844 i == Ylenses_eat ? action :
5845 i == Ymagnify_eat ? action :
5846 i == Ygrass_eat ? action :
5847 i == Ydirt_eat ? action :
5848 i == Xsand_stonein_1 ? action :
5849 i == Xsand_stonein_2 ? action :
5850 i == Xsand_stonein_3 ? action :
5851 i == Xsand_stonein_4 ? action :
5852 i == Xsand_stoneout_1 ? action :
5853 i == Xsand_stoneout_2 ? action :
5854 i == Xboom_android ? ACTION_EXPLODING :
5855 action_exploding ? ACTION_EXPLODING :
5856 action_active ? action :
5857 action_other ? action :
5859 int graphic = (el_act_dir2img(effective_element, effective_action,
5861 int crumbled = (el_act_dir2crm(effective_element, effective_action,
5863 int base_graphic = el_act2img(effective_element, ACTION_DEFAULT);
5864 int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT);
5865 boolean has_crumbled_graphics = (base_crumbled != base_graphic);
5866 struct GraphicInfo *g = &graphic_info[graphic];
5867 struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
5870 /* ensure to get symmetric 3-frame, 2-delay animations as used in EM */
5871 boolean special_animation = (action != ACTION_DEFAULT &&
5872 g->anim_frames == 3 &&
5873 g->anim_delay == 2 &&
5874 g->anim_mode & ANIM_LINEAR);
5875 int sync_frame = (i == Xdrip_stretch ? 7 :
5876 i == Xdrip_stretchB ? 7 :
5877 i == Ydrip_s2 ? j + 8 :
5878 i == Ydrip_s2B ? j + 8 :
5887 i == Xfake_acid_1 ? 0 :
5888 i == Xfake_acid_2 ? 10 :
5889 i == Xfake_acid_3 ? 20 :
5890 i == Xfake_acid_4 ? 30 :
5891 i == Xfake_acid_5 ? 40 :
5892 i == Xfake_acid_6 ? 50 :
5893 i == Xfake_acid_7 ? 60 :
5894 i == Xfake_acid_8 ? 70 :
5896 i == Xball_2B ? j + 8 :
5897 i == Yball_eat ? j + 1 :
5898 i == Ykey_1_eat ? j + 1 :
5899 i == Ykey_2_eat ? j + 1 :
5900 i == Ykey_3_eat ? j + 1 :
5901 i == Ykey_4_eat ? j + 1 :
5902 i == Ykey_5_eat ? j + 1 :
5903 i == Ykey_6_eat ? j + 1 :
5904 i == Ykey_7_eat ? j + 1 :
5905 i == Ykey_8_eat ? j + 1 :
5906 i == Ylenses_eat ? j + 1 :
5907 i == Ymagnify_eat ? j + 1 :
5908 i == Ygrass_eat ? j + 1 :
5909 i == Ydirt_eat ? j + 1 :
5910 i == Xamoeba_1 ? 0 :
5911 i == Xamoeba_2 ? 1 :
5912 i == Xamoeba_3 ? 2 :
5913 i == Xamoeba_4 ? 3 :
5914 i == Xamoeba_5 ? 0 :
5915 i == Xamoeba_6 ? 1 :
5916 i == Xamoeba_7 ? 2 :
5917 i == Xamoeba_8 ? 3 :
5918 i == Xexit_2 ? j + 8 :
5919 i == Xexit_3 ? j + 16 :
5920 i == Xdynamite_1 ? 0 :
5921 i == Xdynamite_2 ? 20 :
5922 i == Xdynamite_3 ? 40 :
5923 i == Xdynamite_4 ? 60 :
5924 i == Xsand_stonein_1 ? j + 1 :
5925 i == Xsand_stonein_2 ? j + 9 :
5926 i == Xsand_stonein_3 ? j + 17 :
5927 i == Xsand_stonein_4 ? j + 25 :
5928 i == Xsand_stoneout_1 && j == 0 ? 0 :
5929 i == Xsand_stoneout_1 && j == 1 ? 0 :
5930 i == Xsand_stoneout_1 && j == 2 ? 1 :
5931 i == Xsand_stoneout_1 && j == 3 ? 2 :
5932 i == Xsand_stoneout_1 && j == 4 ? 2 :
5933 i == Xsand_stoneout_1 && j == 5 ? 3 :
5934 i == Xsand_stoneout_1 && j == 6 ? 4 :
5935 i == Xsand_stoneout_1 && j == 7 ? 4 :
5936 i == Xsand_stoneout_2 && j == 0 ? 5 :
5937 i == Xsand_stoneout_2 && j == 1 ? 6 :
5938 i == Xsand_stoneout_2 && j == 2 ? 7 :
5939 i == Xsand_stoneout_2 && j == 3 ? 8 :
5940 i == Xsand_stoneout_2 && j == 4 ? 9 :
5941 i == Xsand_stoneout_2 && j == 5 ? 11 :
5942 i == Xsand_stoneout_2 && j == 6 ? 13 :
5943 i == Xsand_stoneout_2 && j == 7 ? 15 :
5944 i == Xboom_bug && j == 1 ? 2 :
5945 i == Xboom_bug && j == 2 ? 2 :
5946 i == Xboom_bug && j == 3 ? 4 :
5947 i == Xboom_bug && j == 4 ? 4 :
5948 i == Xboom_bug && j == 5 ? 2 :
5949 i == Xboom_bug && j == 6 ? 2 :
5950 i == Xboom_bug && j == 7 ? 0 :
5951 i == Xboom_bomb && j == 1 ? 2 :
5952 i == Xboom_bomb && j == 2 ? 2 :
5953 i == Xboom_bomb && j == 3 ? 4 :
5954 i == Xboom_bomb && j == 4 ? 4 :
5955 i == Xboom_bomb && j == 5 ? 2 :
5956 i == Xboom_bomb && j == 6 ? 2 :
5957 i == Xboom_bomb && j == 7 ? 0 :
5958 i == Xboom_android && j == 7 ? 6 :
5959 i == Xboom_1 && j == 1 ? 2 :
5960 i == Xboom_1 && j == 2 ? 2 :
5961 i == Xboom_1 && j == 3 ? 4 :
5962 i == Xboom_1 && j == 4 ? 4 :
5963 i == Xboom_1 && j == 5 ? 6 :
5964 i == Xboom_1 && j == 6 ? 6 :
5965 i == Xboom_1 && j == 7 ? 8 :
5966 i == Xboom_2 && j == 0 ? 8 :
5967 i == Xboom_2 && j == 1 ? 8 :
5968 i == Xboom_2 && j == 2 ? 10 :
5969 i == Xboom_2 && j == 3 ? 10 :
5970 i == Xboom_2 && j == 4 ? 10 :
5971 i == Xboom_2 && j == 5 ? 12 :
5972 i == Xboom_2 && j == 6 ? 12 :
5973 i == Xboom_2 && j == 7 ? 12 :
5974 special_animation && j == 4 ? 3 :
5975 effective_action != action ? 0 :
5979 Bitmap *debug_bitmap = g_em->bitmap;
5980 int debug_src_x = g_em->src_x;
5981 int debug_src_y = g_em->src_y;
5984 int frame = getAnimationFrame(g->anim_frames,
5987 g->anim_start_frame,
5990 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y,
5991 g->double_movement && is_backside);
5994 g_em->bitmap = src_bitmap;
5995 g_em->src_x = src_x;
5996 g_em->src_y = src_y;
5997 g_em->src_offset_x = 0;
5998 g_em->src_offset_y = 0;
5999 g_em->dst_offset_x = 0;
6000 g_em->dst_offset_y = 0;
6001 g_em->width = TILEX;
6002 g_em->height = TILEY;
6004 g_em->crumbled_bitmap = NULL;
6005 g_em->crumbled_src_x = 0;
6006 g_em->crumbled_src_y = 0;
6007 g_em->crumbled_border_size = 0;
6009 g_em->has_crumbled_graphics = FALSE;
6010 g_em->preserve_background = FALSE;
6014 if (effective_element == EL_EMC_GRASS &&
6015 effective_action == ACTION_DIGGING)
6016 printf("::: %d\n", crumbled);
6020 if (has_crumbled_graphics && crumbled == IMG_EMPTY_SPACE)
6021 printf("::: empty crumbled: %d [%s], %d, %d\n",
6022 effective_element, element_info[effective_element].token_name,
6023 effective_action, direction);
6026 /* if element can be crumbled, but certain action graphics are just empty
6027 space (like snapping sand with the original R'n'D graphics), do not
6028 treat these empty space graphics as crumbled graphics in EMC engine */
6029 if (has_crumbled_graphics && crumbled != IMG_EMPTY_SPACE)
6031 getGraphicSource(crumbled, frame, &src_bitmap, &src_x, &src_y);
6033 g_em->has_crumbled_graphics = TRUE;
6034 g_em->crumbled_bitmap = src_bitmap;
6035 g_em->crumbled_src_x = src_x;
6036 g_em->crumbled_src_y = src_y;
6037 g_em->crumbled_border_size = graphic_info[crumbled].border_size;
6041 if (!g->double_movement && (effective_action == ACTION_FALLING ||
6042 effective_action == ACTION_MOVING ||
6043 effective_action == ACTION_PUSHING))
6046 (effective_action == ACTION_FALLING ? MV_DOWN : direction);
6047 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? 1 : 0);
6048 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? 1 : 0);
6049 int num_steps = (i == Ydrip_s1 ||
6052 i == Ydrip_s2B ? 16 : 8);
6053 int cx = ABS(dx) * (TILEX / num_steps);
6054 int cy = ABS(dy) * (TILEY / num_steps);
6055 int step_frame = (i == Ydrip_s2 ||
6056 i == Ydrip_s2B ? j + 8 : j) + 1;
6057 int step = (is_backside ? step_frame : num_steps - step_frame);
6059 if (is_backside) /* tile where movement starts */
6061 if (dx < 0 || dy < 0)
6063 g_em->src_offset_x = cx * step;
6064 g_em->src_offset_y = cy * step;
6068 g_em->dst_offset_x = cx * step;
6069 g_em->dst_offset_y = cy * step;
6072 else /* tile where movement ends */
6074 if (dx < 0 || dy < 0)
6076 g_em->dst_offset_x = cx * step;
6077 g_em->dst_offset_y = cy * step;
6081 g_em->src_offset_x = cx * step;
6082 g_em->src_offset_y = cy * step;
6086 g_em->width = TILEX - cx * step;
6087 g_em->height = TILEY - cy * step;
6091 if (effective_action == ACTION_SMASHED_BY_ROCK &&
6092 element_info[effective_element].graphic[effective_action] ==
6093 element_info[effective_element].graphic[ACTION_DEFAULT])
6095 int move_dir = MV_DOWN;
6096 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? 1 : 0);
6097 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? 1 : 0);
6099 int cx = ABS(dx) * (TILEX / num_steps);
6100 int cy = ABS(dy) * (TILEY / num_steps);
6101 int step_frame = j + 1;
6102 int step = (is_backside ? step_frame : num_steps - step_frame);
6104 graphic = (el_act_dir2img(EL_ROCK, ACTION_FALLING, MV_DOWN));
6105 g = &graphic_info[graphic];
6107 frame = getAnimationFrame(g->anim_frames,
6110 g->anim_start_frame,
6112 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y,
6113 g->double_movement && is_backside);
6115 g_em->bitmap = src_bitmap;
6116 g_em->src_x = src_x;
6117 g_em->src_y = src_y;
6118 g_em->src_offset_x = 0;
6119 g_em->src_offset_y = 0;
6120 g_em->dst_offset_x = 0;
6121 g_em->dst_offset_y = 0;
6123 if (is_backside) /* tile where movement starts */
6125 if (dx < 0 || dy < 0)
6127 g_em->src_offset_x = cx * step;
6128 g_em->src_offset_y = cy * step;
6132 g_em->dst_offset_x = cx * step;
6133 g_em->dst_offset_y = cy * step;
6136 else /* tile where movement ends */
6138 if (dx < 0 || dy < 0)
6140 g_em->dst_offset_x = cx * step;
6141 g_em->dst_offset_y = cy * step;
6145 g_em->src_offset_x = cx * step;
6146 g_em->src_offset_y = cy * step;
6150 g_em->width = TILEX - cx * step;
6151 g_em->height = TILEY - cy * step;
6154 printf("::: -> '%s'\n", element_info[effective_element].token_name);
6161 /* create unique graphic identifier to decide if tile must be redrawn */
6162 /* bit 31 - 16 (16 bit): EM style element
6163 bit 15 - 12 ( 4 bit): EM style frame
6164 bit 11 - 6 ( 6 bit): graphic width
6165 bit 5 - 0 ( 6 bit): graphic height */
6166 g_em->unique_identifier =
6167 (i << 16) | (j << 12) | (g_em->width << 6) | g_em->height;
6170 if (g_em->bitmap != debug_bitmap ||
6171 g_em->src_x != debug_src_x ||
6172 g_em->src_y != debug_src_y ||
6173 g_em->src_offset_x != 0 ||
6174 g_em->src_offset_y != 0 ||
6175 g_em->dst_offset_x != 0 ||
6176 g_em->dst_offset_y != 0 ||
6177 g_em->width != TILEX ||
6178 g_em->height != TILEY)
6180 static int last_i = -1;
6188 printf("::: EMC GFX ERROR for element %d -> %d ('%s', '%s', %d)",
6189 i, element, element_info[element].token_name,
6190 element_action_info[effective_action].suffix, direction);
6192 if (element != effective_element)
6193 printf(" [%d ('%s')]",
6195 element_info[effective_element].token_name);
6199 if (g_em->bitmap != debug_bitmap)
6200 printf(" %d (%d): different bitmap! (0x%08x != 0x%08x)\n",
6201 j, is_backside, (int)(g_em->bitmap), (int)(debug_bitmap));
6203 if (g_em->src_x != debug_src_x ||
6204 g_em->src_y != debug_src_y)
6205 printf(" frame %d (%c): %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
6206 j, (is_backside ? 'B' : 'F'),
6207 g_em->src_x, g_em->src_y,
6208 g_em->src_x / 32, g_em->src_y / 32,
6209 debug_src_x, debug_src_y,
6210 debug_src_x / 32, debug_src_y / 32);
6212 if (g_em->src_offset_x != 0 ||
6213 g_em->src_offset_y != 0 ||
6214 g_em->dst_offset_x != 0 ||
6215 g_em->dst_offset_y != 0)
6216 printf(" %d (%d): offsets %d,%d and %d,%d should be all 0\n",
6218 g_em->src_offset_x, g_em->src_offset_y,
6219 g_em->dst_offset_x, g_em->dst_offset_y);
6221 if (g_em->width != TILEX ||
6222 g_em->height != TILEY)
6223 printf(" %d (%d): size %d,%d should be %d,%d\n",
6225 g_em->width, g_em->height, TILEX, TILEY);
6233 for (i = 0; i < TILE_MAX; i++)
6235 for (j = 0; j < 8; j++)
6237 int element = object_mapping[i].element_rnd;
6238 int action = object_mapping[i].action;
6240 if (action == ACTION_SMASHED_BY_ROCK &&
6241 element_info[element].graphic[action] ==
6242 element_info[element].graphic[ACTION_DEFAULT])
6244 /* no separate animation for "smashed by rock" -- use rock instead */
6245 struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
6246 struct GraphicInfo_EM *g_xx = &graphic_info_em_object[Ystone_s][7 - j];
6248 g_em->bitmap = g_xx->bitmap;
6249 g_em->src_x = g_xx->src_x;
6250 g_em->src_y = g_xx->src_y;
6251 g_em->src_offset_x = g_xx->src_offset_x;
6252 g_em->src_offset_y = g_xx->src_offset_y;
6253 g_em->dst_offset_x = g_xx->dst_offset_x;
6254 g_em->dst_offset_y = g_xx->dst_offset_y;
6255 g_em->width = g_xx->width;
6256 g_em->height = g_xx->height;
6258 g_em->preserve_background = TRUE;
6264 for (p = 0; p < 2; p++)
6266 for (i = 0; i < SPR_MAX; i++)
6268 int element = player_mapping[p][i].element_rnd;
6269 int action = player_mapping[p][i].action;
6270 int direction = player_mapping[p][i].direction;
6272 for (j = 0; j < 8; j++)
6274 int effective_element = element;
6275 int effective_action = action;
6276 int graphic = (direction == MV_NO_MOVING ?
6277 el_act2img(effective_element, effective_action) :
6278 el_act_dir2img(effective_element, effective_action,
6280 struct GraphicInfo *g = &graphic_info[graphic];
6281 struct GraphicInfo_EM *g_em = &graphic_info_em_player[p][i][7 - j];
6287 Bitmap *debug_bitmap = g_em->bitmap;
6288 int debug_src_x = g_em->src_x;
6289 int debug_src_y = g_em->src_y;
6292 int frame = getAnimationFrame(g->anim_frames,
6295 g->anim_start_frame,
6298 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x,&src_y, FALSE);
6301 g_em->bitmap = src_bitmap;
6302 g_em->src_x = src_x;
6303 g_em->src_y = src_y;
6304 g_em->src_offset_x = 0;
6305 g_em->src_offset_y = 0;
6306 g_em->dst_offset_x = 0;
6307 g_em->dst_offset_y = 0;
6308 g_em->width = TILEX;
6309 g_em->height = TILEY;
6313 if (g_em->bitmap != debug_bitmap ||
6314 g_em->src_x != debug_src_x ||
6315 g_em->src_y != debug_src_y)
6317 static int last_i = -1;
6325 printf("::: EMC GFX ERROR for p/a %d/%d -> %d ('%s', '%s', %d)",
6326 p, i, element, element_info[element].token_name,
6327 element_action_info[effective_action].suffix, direction);
6329 if (element != effective_element)
6330 printf(" [%d ('%s')]",
6332 element_info[effective_element].token_name);
6336 if (g_em->bitmap != debug_bitmap)
6337 printf(" %d: different bitmap! (0x%08x != 0x%08x)\n",
6338 j, (int)(g_em->bitmap), (int)(debug_bitmap));
6340 if (g_em->src_x != debug_src_x ||
6341 g_em->src_y != debug_src_y)
6342 printf(" frame %d: %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
6344 g_em->src_x, g_em->src_y,
6345 g_em->src_x / 32, g_em->src_y / 32,
6346 debug_src_x, debug_src_y,
6347 debug_src_x / 32, debug_src_y / 32);