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 RedrawPlayfield_EM();
134 if (game_status == GAME_MODE_PLAYING && !game.envelope_active)
140 width = gfx.sxsize + 2 * TILEX;
141 height = gfx.sysize + 2 * TILEY;
144 if (force_redraw || setup.direct_draw)
147 int x1 = (x - SX) / TILEX, y1 = (y - SY) / TILEY;
148 int x2 = (x - SX + width) / TILEX, y2 = (y - SY + height) / TILEY;
150 if (setup.direct_draw)
151 SetDrawtoField(DRAW_BACKBUFFER);
153 for (xx = BX1; xx <= BX2; xx++)
154 for (yy = BY1; yy <= BY2; yy++)
155 if (xx >= x1 && xx <= x2 && yy >= y1 && yy <= y2)
156 DrawScreenField(xx, yy);
159 if (setup.direct_draw)
160 SetDrawtoField(DRAW_DIRECT);
163 if (setup.soft_scrolling)
165 int fx = FX, fy = FY;
167 fx += (ScreenMovDir & (MV_LEFT|MV_RIGHT) ? ScreenGfxPos : 0);
168 fy += (ScreenMovDir & (MV_UP|MV_DOWN) ? ScreenGfxPos : 0);
170 BlitBitmap(fieldbuffer, backbuffer, fx,fy, SXSIZE,SYSIZE, SX,SY);
174 BlitBitmap(drawto, window, x, y, width, height, x, y);
180 DrawBuffer *buffer = (drawto_field == window ? backbuffer : drawto_field);
182 if (setup.direct_draw && game_status == GAME_MODE_PLAYING)
183 redraw_mask &= ~REDRAW_MAIN;
185 if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD)
186 redraw_mask |= REDRAW_FIELD;
188 if (redraw_mask & REDRAW_FIELD)
189 redraw_mask &= ~REDRAW_TILES;
191 if (redraw_mask == REDRAW_NONE)
194 if (global.fps_slowdown && game_status == GAME_MODE_PLAYING)
196 static boolean last_frame_skipped = FALSE;
197 boolean skip_even_when_not_scrolling = TRUE;
198 boolean just_scrolling = (ScreenMovDir != 0);
199 boolean verbose = FALSE;
201 if (global.fps_slowdown_factor > 1 &&
202 (FrameCounter % global.fps_slowdown_factor) &&
203 (just_scrolling || skip_even_when_not_scrolling))
205 redraw_mask &= ~REDRAW_MAIN;
207 last_frame_skipped = TRUE;
210 printf("FRAME SKIPPED\n");
214 if (last_frame_skipped)
215 redraw_mask |= REDRAW_FIELD;
217 last_frame_skipped = FALSE;
220 printf("frame not skipped\n");
224 /* synchronize X11 graphics at this point; if we would synchronize the
225 display immediately after the buffer switching (after the XFlush),
226 this could mean that we have to wait for the graphics to complete,
227 although we could go on doing calculations for the next frame */
231 if (redraw_mask & REDRAW_ALL)
233 BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
237 if (redraw_mask & REDRAW_FIELD)
239 if (game_status != GAME_MODE_PLAYING ||
240 redraw_mask & REDRAW_FROM_BACKBUFFER)
242 BlitBitmap(backbuffer, window,
243 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE, REAL_SX, REAL_SY);
247 int fx = FX, fy = FY;
249 if (setup.soft_scrolling)
251 fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
252 fy += (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
255 if (setup.soft_scrolling ||
256 ABS(ScreenMovPos) + ScrollStepSize == TILEX ||
257 ABS(ScreenMovPos) == ScrollStepSize ||
258 redraw_tiles > REDRAWTILES_THRESHOLD)
260 BlitBitmap(buffer, window, fx, fy, SXSIZE, SYSIZE, SX, SY);
264 printf("redrawing all (ScreenGfxPos == %d) because %s\n",
266 (setup.soft_scrolling ?
267 "setup.soft_scrolling" :
268 ABS(ScreenGfxPos) + ScrollStepSize == TILEX ?
269 "ABS(ScreenGfxPos) + ScrollStepSize == TILEX" :
270 ABS(ScreenGfxPos) == ScrollStepSize ?
271 "ABS(ScreenGfxPos) == ScrollStepSize" :
272 "redraw_tiles > REDRAWTILES_THRESHOLD"));
278 redraw_mask &= ~REDRAW_MAIN;
281 if (redraw_mask & REDRAW_DOORS)
283 if (redraw_mask & REDRAW_DOOR_1)
284 BlitBitmap(backbuffer, window, DX, DY, DXSIZE, DYSIZE, DX, DY);
286 if (redraw_mask & REDRAW_DOOR_2)
289 if ((redraw_mask & REDRAW_DOOR_2) == REDRAW_DOOR_2)
291 BlitBitmap(backbuffer, window, VX, VY, VXSIZE, VYSIZE, VX, VY);
295 if (redraw_mask & REDRAW_VIDEO_1)
296 BlitBitmap(backbuffer, window,
297 VX + VIDEO_DISPLAY1_XPOS, VY + VIDEO_DISPLAY1_YPOS,
298 VIDEO_DISPLAY_XSIZE, VIDEO_DISPLAY_YSIZE,
299 VX + VIDEO_DISPLAY1_XPOS, VY + VIDEO_DISPLAY1_YPOS);
300 if (redraw_mask & REDRAW_VIDEO_2)
301 BlitBitmap(backbuffer, window,
302 VX + VIDEO_DISPLAY2_XPOS, VY + VIDEO_DISPLAY2_YPOS,
303 VIDEO_DISPLAY_XSIZE, VIDEO_DISPLAY_YSIZE,
304 VX + VIDEO_DISPLAY2_XPOS, VY + VIDEO_DISPLAY2_YPOS);
305 if (redraw_mask & REDRAW_VIDEO_3)
306 BlitBitmap(backbuffer, window,
307 VX + VIDEO_CONTROL_XPOS, VY + VIDEO_CONTROL_YPOS,
308 VIDEO_CONTROL_XSIZE, VIDEO_CONTROL_YSIZE,
309 VX + VIDEO_CONTROL_XPOS, VY + VIDEO_CONTROL_YPOS);
314 if (redraw_mask & REDRAW_DOOR_3)
315 BlitBitmap(backbuffer, window, EX, EY, EXSIZE, EYSIZE, EX, EY);
317 redraw_mask &= ~REDRAW_DOORS;
320 if (redraw_mask & REDRAW_MICROLEVEL)
322 BlitBitmap(backbuffer, window, SX, SY + 10 * TILEY, SXSIZE, 7 * TILEY,
323 SX, SY + 10 * TILEY);
325 redraw_mask &= ~REDRAW_MICROLEVEL;
328 if (redraw_mask & REDRAW_TILES)
330 for (x = 0; x < SCR_FIELDX; x++)
331 for (y = 0 ; y < SCR_FIELDY; y++)
332 if (redraw[redraw_x1 + x][redraw_y1 + y])
333 BlitBitmap(buffer, window,
334 FX + x * TILEX, FY + y * TILEY, TILEX, TILEY,
335 SX + x * TILEX, SY + y * TILEY);
338 if (redraw_mask & REDRAW_FPS) /* display frames per second */
343 sprintf(info1, " (only every %d. frame)", global.fps_slowdown_factor);
344 if (!global.fps_slowdown)
347 sprintf(text, "%.1f fps%s", global.frames_per_second, info1);
348 DrawTextExt(window, SX, SY, text, FONT_TEXT_2, BLIT_OPAQUE);
353 for (x = 0; x < MAX_BUF_XSIZE; x++)
354 for (y = 0; y < MAX_BUF_YSIZE; y++)
357 redraw_mask = REDRAW_NONE;
363 long fading_delay = 300;
365 if (setup.fading && (redraw_mask & REDRAW_FIELD))
372 ClearRectangle(window, REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
375 for (i = 0; i < 2 * FULL_SYSIZE; i++)
377 for (y = 0; y < FULL_SYSIZE; y++)
379 BlitBitmap(backbuffer, window,
380 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
388 for (i = 1; i < FULL_SYSIZE; i+=2)
389 BlitBitmap(backbuffer, window,
390 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
396 SetClipOrigin(clip_gc[PIX_FADEMASK], 0, 0);
397 BlitBitmapMasked(backbuffer, window,
398 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
403 SetClipOrigin(clip_gc[PIX_FADEMASK], -1, -1);
404 BlitBitmapMasked(backbuffer, window,
405 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
410 SetClipOrigin(clip_gc[PIX_FADEMASK], 0, -1);
411 BlitBitmapMasked(backbuffer, window,
412 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
417 SetClipOrigin(clip_gc[PIX_FADEMASK], -1, 0);
418 BlitBitmapMasked(backbuffer, window,
419 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
424 redraw_mask &= ~REDRAW_MAIN;
431 void SetMainBackgroundImage(int graphic)
433 SetMainBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
434 graphic_info[graphic].bitmap ?
435 graphic_info[graphic].bitmap :
436 graphic_info[IMG_BACKGROUND].bitmap);
439 void SetDoorBackgroundImage(int graphic)
441 SetDoorBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
442 graphic_info[graphic].bitmap ?
443 graphic_info[graphic].bitmap :
444 graphic_info[IMG_BACKGROUND].bitmap);
447 void DrawBackground(int dst_x, int dst_y, int width, int height)
449 ClearRectangleOnBackground(backbuffer, dst_x, dst_y, width, height);
451 redraw_mask |= REDRAW_FIELD;
456 DrawBackground(REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
458 if (setup.soft_scrolling && game_status == GAME_MODE_PLAYING)
460 ClearRectangle(fieldbuffer, 0, 0, FXSIZE, FYSIZE);
461 SetDrawtoField(DRAW_BUFFERED);
464 SetDrawtoField(DRAW_BACKBUFFER);
466 if (setup.direct_draw && game_status == GAME_MODE_PLAYING)
468 ClearRectangle(window, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
469 SetDrawtoField(DRAW_DIRECT);
473 void MarkTileDirty(int x, int y)
475 int xx = redraw_x1 + x;
476 int yy = redraw_y1 + y;
481 redraw[xx][yy] = TRUE;
482 redraw_mask |= REDRAW_TILES;
485 void SetBorderElement()
489 BorderElement = EL_EMPTY;
491 for (y = 0; y < lev_fieldy && BorderElement == EL_EMPTY; y++)
493 for (x = 0; x < lev_fieldx; x++)
495 if (!IS_INDESTRUCTIBLE(Feld[x][y]))
496 BorderElement = EL_STEELWALL;
498 if (y != 0 && y != lev_fieldy - 1 && x != lev_fieldx - 1)
504 void SetRandomAnimationValue(int x, int y)
506 gfx.anim_random_frame = GfxRandom[x][y];
509 inline int getGraphicAnimationFrame(int graphic, int sync_frame)
511 /* animation synchronized with global frame counter, not move position */
512 if (graphic_info[graphic].anim_global_sync || sync_frame < 0)
513 sync_frame = FrameCounter;
515 return getAnimationFrame(graphic_info[graphic].anim_frames,
516 graphic_info[graphic].anim_delay,
517 graphic_info[graphic].anim_mode,
518 graphic_info[graphic].anim_start_frame,
522 inline void getGraphicSourceExt(int graphic, int frame, Bitmap **bitmap,
523 int *x, int *y, boolean get_backside)
525 struct GraphicInfo *g = &graphic_info[graphic];
526 int src_x = g->src_x + (get_backside ? g->offset2_x : 0);
527 int src_y = g->src_y + (get_backside ? g->offset2_y : 0);
531 if (g->offset_y == 0) /* frames are ordered horizontally */
533 int max_width = g->anim_frames_per_line * g->width;
535 int pos = (src_y / g->height) * max_width + src_x + frame * g->offset_x;
537 *x = pos % max_width;
538 *y = src_y % g->height + pos / max_width * g->height;
540 *x = (src_x + frame * g->offset_x) % max_width;
541 *y = src_y + (src_x + frame * g->offset_x) / max_width * g->height;
544 else if (g->offset_x == 0) /* frames are ordered vertically */
546 int max_height = g->anim_frames_per_line * g->height;
548 int pos = (src_x / g->width) * max_height + src_y + frame * g->offset_y;
550 *x = src_x % g->width + pos / max_height * g->width;
551 *y = pos % max_height;
553 *x = src_x + (src_y + frame * g->offset_y) / max_height * g->width;
554 *y = (src_y + frame * g->offset_y) % max_height;
557 else /* frames are ordered diagonally */
559 *x = src_x + frame * g->offset_x;
560 *y = src_y + frame * g->offset_y;
564 void getGraphicSource(int graphic, int frame, Bitmap **bitmap, int *x, int *y)
566 getGraphicSourceExt(graphic, frame, bitmap, x, y, FALSE);
569 void DrawGraphic(int x, int y, int graphic, int frame)
572 if (!IN_SCR_FIELD(x, y))
574 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
575 printf("DrawGraphic(): This should never happen!\n");
580 DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic, frame);
584 void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
590 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
591 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
594 void DrawGraphicThruMask(int x, int y, int graphic, int frame)
597 if (!IN_SCR_FIELD(x, y))
599 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
600 printf("DrawGraphicThruMask(): This should never happen!\n");
605 DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY, graphic,
610 void DrawGraphicThruMaskExt(DrawBuffer *d, int dst_x, int dst_y, int graphic,
616 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
618 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
619 dst_x - src_x, dst_y - src_y);
620 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dst_x, dst_y);
623 void DrawMiniGraphic(int x, int y, int graphic)
625 DrawMiniGraphicExt(drawto, SX + x * MINI_TILEX,SY + y * MINI_TILEY, graphic);
626 MarkTileDirty(x / 2, y / 2);
629 void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
631 struct GraphicInfo *g = &graphic_info[graphic];
633 int mini_starty = g->bitmap->height * 2 / 3;
636 *x = mini_startx + g->src_x / 2;
637 *y = mini_starty + g->src_y / 2;
640 void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
645 getMiniGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
646 BlitBitmap(src_bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
649 inline static void DrawGraphicShiftedNormal(int x, int y, int dx, int dy,
650 int graphic, int frame,
651 int cut_mode, int mask_mode)
656 int width = TILEX, height = TILEY;
659 if (dx || dy) /* shifted graphic */
661 if (x < BX1) /* object enters playfield from the left */
668 else if (x > BX2) /* object enters playfield from the right */
674 else if (x==BX1 && dx < 0) /* object leaves playfield to the left */
680 else if (x==BX2 && dx > 0) /* object leaves playfield to the right */
682 else if (dx) /* general horizontal movement */
683 MarkTileDirty(x + SIGN(dx), y);
685 if (y < BY1) /* object enters playfield from the top */
687 if (cut_mode==CUT_BELOW) /* object completely above top border */
695 else if (y > BY2) /* object enters playfield from the bottom */
701 else if (y==BY1 && dy < 0) /* object leaves playfield to the top */
707 else if (dy > 0 && cut_mode == CUT_ABOVE)
709 if (y == BY2) /* object completely above bottom border */
715 MarkTileDirty(x, y + 1);
716 } /* object leaves playfield to the bottom */
717 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
719 else if (dy) /* general vertical movement */
720 MarkTileDirty(x, y + SIGN(dy));
724 if (!IN_SCR_FIELD(x, y))
726 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
727 printf("DrawGraphicShifted(): This should never happen!\n");
732 if (width > 0 && height > 0)
734 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
739 dst_x = FX + x * TILEX + dx;
740 dst_y = FY + y * TILEY + dy;
742 if (mask_mode == USE_MASKING)
744 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
745 dst_x - src_x, dst_y - src_y);
746 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
750 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
757 inline static void DrawGraphicShiftedDouble(int x, int y, int dx, int dy,
758 int graphic, int frame,
759 int cut_mode, int mask_mode)
764 int width = TILEX, height = TILEY;
767 int x2 = x + SIGN(dx);
768 int y2 = y + SIGN(dy);
769 int anim_frames = graphic_info[graphic].anim_frames;
770 int sync_frame = (dx ? ABS(dx) : ABS(dy)) * anim_frames / TILESIZE;
772 /* re-calculate animation frame for two-tile movement animation */
773 frame = getGraphicAnimationFrame(graphic, sync_frame);
775 if (IN_SCR_FIELD(x1, y1)) /* movement start graphic inside screen area */
777 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, TRUE);
779 dst_x = FX + x1 * TILEX;
780 dst_y = FY + y1 * TILEY;
782 if (mask_mode == USE_MASKING)
784 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
785 dst_x - src_x, dst_y - src_y);
786 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
790 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
793 MarkTileDirty(x1, y1);
796 if (IN_SCR_FIELD(x2, y2)) /* movement end graphic inside screen area */
798 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, FALSE);
800 dst_x = FX + x2 * TILEX;
801 dst_y = FY + y2 * TILEY;
803 if (mask_mode == USE_MASKING)
805 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
806 dst_x - src_x, dst_y - src_y);
807 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
811 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
814 MarkTileDirty(x2, y2);
818 printf("::: DONE DrawGraphicShiftedDouble");
824 static void DrawGraphicShifted(int x, int y, int dx, int dy,
825 int graphic, int frame,
826 int cut_mode, int mask_mode)
830 DrawGraphic(x, y, graphic, frame);
835 if (graphic_info[graphic].double_movement) /* EM style movement images */
836 DrawGraphicShiftedDouble(x, y, dx, dy, graphic, frame, cut_mode,mask_mode);
838 DrawGraphicShiftedNormal(x, y, dx, dy, graphic, frame, cut_mode,mask_mode);
841 void DrawGraphicShiftedThruMask(int x, int y, int dx, int dy, int graphic,
842 int frame, int cut_mode)
844 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, USE_MASKING);
847 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
848 int cut_mode, int mask_mode)
850 int lx = LEVELX(x), ly = LEVELY(y);
854 if (IN_LEV_FIELD(lx, ly))
856 SetRandomAnimationValue(lx, ly);
858 graphic = el_act_dir2img(element, GfxAction[lx][ly], GfxDir[lx][ly]);
859 frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
861 /* do not use double (EM style) movement graphic when not moving */
862 if (graphic_info[graphic].double_movement && !dx && !dy)
864 graphic = el_act_dir2img(element, ACTION_DEFAULT, GfxDir[lx][ly]);
865 frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
868 else /* border element */
870 graphic = el2img(element);
871 frame = getGraphicAnimationFrame(graphic, -1);
874 if (element == EL_EXPANDABLE_WALL)
876 boolean left_stopped = FALSE, right_stopped = FALSE;
878 if (!IN_LEV_FIELD(lx - 1, ly) || IS_WALL(Feld[lx - 1][ly]))
880 if (!IN_LEV_FIELD(lx + 1, ly) || IS_WALL(Feld[lx + 1][ly]))
881 right_stopped = TRUE;
883 if (left_stopped && right_stopped)
885 else if (left_stopped)
887 graphic = IMG_EXPANDABLE_WALL_GROWING_RIGHT;
888 frame = graphic_info[graphic].anim_frames - 1;
890 else if (right_stopped)
892 graphic = IMG_EXPANDABLE_WALL_GROWING_LEFT;
893 frame = graphic_info[graphic].anim_frames - 1;
898 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
899 else if (mask_mode == USE_MASKING)
900 DrawGraphicThruMask(x, y, graphic, frame);
902 DrawGraphic(x, y, graphic, frame);
905 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
906 int cut_mode, int mask_mode)
908 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
909 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
910 cut_mode, mask_mode);
913 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
916 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
919 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
922 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
925 void DrawLevelElementThruMask(int x, int y, int element)
927 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
930 void DrawLevelFieldThruMask(int x, int y)
932 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
935 #define TILE_GFX_ELEMENT(x, y) \
936 (GfxElement[x][y] != EL_UNDEFINED && Feld[x][y] != EL_EXPLOSION ? \
937 GfxElement[x][y] : Feld[x][y])
939 static void DrawLevelFieldCrumbledSandExt(int x, int y, int graphic, int frame)
943 int sx = SCREENX(x), sy = SCREENY(y);
945 int width, height, cx, cy, i;
947 int crumbled_border_size = graphic_info[graphic].border_size;
949 int snip = TILEX / 8; /* number of border pixels from "crumbled graphic" */
951 static int xy[4][2] =
960 if (x == 0 && y == 7)
961 printf("::: %d, %d [%d]\n", GfxElement[x][y], Feld[x][y],
962 crumbled_border_size);
965 if (!IN_LEV_FIELD(x, y))
968 element = TILE_GFX_ELEMENT(x, y);
970 /* crumble field itself */
971 if (GFX_CRUMBLED(element) && !IS_MOVING(x, y))
973 if (!IN_SCR_FIELD(sx, sy))
976 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
978 for (i = 0; i < 4; i++)
980 int xx = x + xy[i][0];
981 int yy = y + xy[i][1];
984 element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
987 element = (IN_LEV_FIELD(xx, yy) ? Feld[xx][yy] : BorderElement);
990 /* check if neighbour field is of same type */
991 if (GFX_CRUMBLED(element) && !IS_MOVING(xx, yy))
995 if (Feld[x][y] == EL_CUSTOM_START + 123)
996 printf("::: crumble [%d] THE CHAOS ENGINE (%d, %d): %d, %d\n",
997 i, Feld[x][y], element,
998 GFX_CRUMBLED(element), IS_MOVING(x, y));
1001 if (i == 1 || i == 2)
1003 width = crumbled_border_size;
1005 cx = (i == 2 ? TILEX - crumbled_border_size : 0);
1011 height = crumbled_border_size;
1013 cy = (i == 3 ? TILEY - crumbled_border_size : 0);
1016 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1017 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
1020 MarkTileDirty(sx, sy);
1022 else /* crumble neighbour fields */
1025 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1028 for (i = 0; i < 4; i++)
1030 int xx = x + xy[i][0];
1031 int yy = y + xy[i][1];
1032 int sxx = sx + xy[i][0];
1033 int syy = sy + xy[i][1];
1036 if (!IN_LEV_FIELD(xx, yy) ||
1037 !IN_SCR_FIELD(sxx, syy) ||
1041 element = TILE_GFX_ELEMENT(xx, yy);
1043 if (!GFX_CRUMBLED(element))
1046 if (!IN_LEV_FIELD(xx, yy) ||
1047 !IN_SCR_FIELD(sxx, syy) ||
1048 !GFX_CRUMBLED(Feld[xx][yy]) ||
1054 graphic = el_act2crm(Feld[xx][yy], ACTION_DEFAULT);
1055 crumbled_border_size = graphic_info[graphic].border_size;
1057 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1060 if (i == 1 || i == 2)
1062 width = crumbled_border_size;
1064 cx = (i == 1 ? TILEX - crumbled_border_size : 0);
1070 height = crumbled_border_size;
1072 cy = (i == 0 ? TILEY - crumbled_border_size : 0);
1075 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1076 width, height, FX + sxx * TILEX + cx, FY + syy * TILEY + cy);
1078 MarkTileDirty(sxx, syy);
1083 void DrawLevelFieldCrumbledSand(int x, int y)
1088 if (!IN_LEV_FIELD(x, y))
1091 graphic = el_act2crm(Feld[x][y], ACTION_DEFAULT);
1093 DrawLevelFieldCrumbledSandExt(x, y, graphic, 0);
1095 DrawLevelFieldCrumbledSandExt(x, y, IMG_SAND_CRUMBLED, 0);
1099 void DrawLevelFieldCrumbledSandDigging(int x, int y, int direction,
1103 int graphic1 = el_act_dir2img(GfxElement[x][y], ACTION_DIGGING, direction);
1104 int graphic2 = el_act_dir2crm(GfxElement[x][y], ACTION_DIGGING, direction);
1106 int graphic1 = el_act_dir2img(EL_SAND, ACTION_DIGGING, direction);
1107 int graphic2 = el_act_dir2img(EL_SAND_CRUMBLED, ACTION_DIGGING, direction);
1109 int frame1 = getGraphicAnimationFrame(graphic1, step_frame);
1110 int frame2 = getGraphicAnimationFrame(graphic2, step_frame);
1111 int sx = SCREENX(x), sy = SCREENY(y);
1113 DrawGraphic(sx, sy, graphic1, frame1);
1114 DrawLevelFieldCrumbledSandExt(x, y, graphic2, frame2);
1117 void DrawLevelFieldCrumbledSandNeighbours(int x, int y)
1119 int sx = SCREENX(x), sy = SCREENY(y);
1120 static int xy[4][2] =
1129 for (i = 0; i < 4; i++)
1131 int xx = x + xy[i][0];
1132 int yy = y + xy[i][1];
1133 int sxx = sx + xy[i][0];
1134 int syy = sy + xy[i][1];
1136 if (!IN_LEV_FIELD(xx, yy) ||
1137 !IN_SCR_FIELD(sxx, syy) ||
1138 !GFX_CRUMBLED(Feld[xx][yy]) ||
1142 DrawLevelField(xx, yy);
1146 static int getBorderElement(int x, int y)
1150 { EL_STEELWALL_TOPLEFT, EL_INVISIBLE_STEELWALL_TOPLEFT },
1151 { EL_STEELWALL_TOPRIGHT, EL_INVISIBLE_STEELWALL_TOPRIGHT },
1152 { EL_STEELWALL_BOTTOMLEFT, EL_INVISIBLE_STEELWALL_BOTTOMLEFT },
1153 { EL_STEELWALL_BOTTOMRIGHT, EL_INVISIBLE_STEELWALL_BOTTOMRIGHT },
1154 { EL_STEELWALL_VERTICAL, EL_INVISIBLE_STEELWALL_VERTICAL },
1155 { EL_STEELWALL_HORIZONTAL, EL_INVISIBLE_STEELWALL_HORIZONTAL },
1156 { EL_STEELWALL, EL_INVISIBLE_STEELWALL }
1158 int steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
1159 int steel_position = (x == -1 && y == -1 ? 0 :
1160 x == lev_fieldx && y == -1 ? 1 :
1161 x == -1 && y == lev_fieldy ? 2 :
1162 x == lev_fieldx && y == lev_fieldy ? 3 :
1163 x == -1 || x == lev_fieldx ? 4 :
1164 y == -1 || y == lev_fieldy ? 5 : 6);
1166 return border[steel_position][steel_type];
1169 void DrawScreenElement(int x, int y, int element)
1171 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1172 DrawLevelFieldCrumbledSand(LEVELX(x), LEVELY(y));
1175 void DrawLevelElement(int x, int y, int element)
1177 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1178 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1181 void DrawScreenField(int x, int y)
1183 int lx = LEVELX(x), ly = LEVELY(y);
1184 int element, content;
1186 if (!IN_LEV_FIELD(lx, ly))
1188 if (lx < -1 || lx > lev_fieldx || ly < -1 || ly > lev_fieldy)
1191 element = getBorderElement(lx, ly);
1193 DrawScreenElement(x, y, element);
1197 element = Feld[lx][ly];
1198 content = Store[lx][ly];
1200 if (IS_MOVING(lx, ly))
1202 int horiz_move = (MovDir[lx][ly] == MV_LEFT || MovDir[lx][ly] == MV_RIGHT);
1203 boolean cut_mode = NO_CUTTING;
1205 if (element == EL_QUICKSAND_EMPTYING ||
1206 element == EL_MAGIC_WALL_EMPTYING ||
1207 element == EL_BD_MAGIC_WALL_EMPTYING ||
1208 element == EL_AMOEBA_DROPPING)
1209 cut_mode = CUT_ABOVE;
1210 else if (element == EL_QUICKSAND_FILLING ||
1211 element == EL_MAGIC_WALL_FILLING ||
1212 element == EL_BD_MAGIC_WALL_FILLING)
1213 cut_mode = CUT_BELOW;
1215 if (cut_mode == CUT_ABOVE)
1216 DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1218 DrawScreenElement(x, y, EL_EMPTY);
1221 DrawScreenElementShifted(x, y, MovPos[lx][ly], 0, element, NO_CUTTING);
1222 else if (cut_mode == NO_CUTTING)
1223 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], element, cut_mode);
1225 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], content, cut_mode);
1227 if (content == EL_ACID)
1229 int dir = MovDir[lx][ly];
1230 int newlx = lx + (dir == MV_LEFT ? -1 : dir == MV_RIGHT ? +1 : 0);
1231 int newly = ly + (dir == MV_UP ? -1 : dir == MV_DOWN ? +1 : 0);
1233 DrawLevelElementThruMask(newlx, newly, EL_ACID);
1236 else if (IS_BLOCKED(lx, ly))
1241 boolean cut_mode = NO_CUTTING;
1242 int element_old, content_old;
1244 Blocked2Moving(lx, ly, &oldx, &oldy);
1247 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1248 MovDir[oldx][oldy] == MV_RIGHT);
1250 element_old = Feld[oldx][oldy];
1251 content_old = Store[oldx][oldy];
1253 if (element_old == EL_QUICKSAND_EMPTYING ||
1254 element_old == EL_MAGIC_WALL_EMPTYING ||
1255 element_old == EL_BD_MAGIC_WALL_EMPTYING ||
1256 element_old == EL_AMOEBA_DROPPING)
1257 cut_mode = CUT_ABOVE;
1259 DrawScreenElement(x, y, EL_EMPTY);
1262 DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
1264 else if (cut_mode == NO_CUTTING)
1265 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
1268 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
1271 else if (IS_DRAWABLE(element))
1272 DrawScreenElement(x, y, element);
1274 DrawScreenElement(x, y, EL_EMPTY);
1277 void DrawLevelField(int x, int y)
1279 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1280 DrawScreenField(SCREENX(x), SCREENY(y));
1281 else if (IS_MOVING(x, y))
1285 Moving2Blocked(x, y, &newx, &newy);
1286 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1287 DrawScreenField(SCREENX(newx), SCREENY(newy));
1289 else if (IS_BLOCKED(x, y))
1293 Blocked2Moving(x, y, &oldx, &oldy);
1294 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1295 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1299 void DrawMiniElement(int x, int y, int element)
1303 graphic = el2edimg(element);
1304 DrawMiniGraphic(x, y, graphic);
1307 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1309 int x = sx + scroll_x, y = sy + scroll_y;
1311 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1312 DrawMiniElement(sx, sy, EL_EMPTY);
1313 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1314 DrawMiniElement(sx, sy, Feld[x][y]);
1316 DrawMiniGraphic(sx, sy, el2edimg(getBorderElement(x, y)));
1319 void DrawEnvelopeBackground(int envelope_nr, int startx, int starty,
1320 int x, int y, int xsize, int ysize, int font_nr)
1322 int font_width = getFontWidth(font_nr);
1323 int font_height = getFontHeight(font_nr);
1324 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1327 int dst_x = SX + startx + x * font_width;
1328 int dst_y = SY + starty + y * font_height;
1329 int width = graphic_info[graphic].width;
1330 int height = graphic_info[graphic].height;
1331 int inner_width = MAX(width - 2 * font_width, font_width);
1332 int inner_height = MAX(height - 2 * font_height, font_height);
1333 int inner_sx = (width >= 3 * font_width ? font_width : 0);
1334 int inner_sy = (height >= 3 * font_height ? font_height : 0);
1335 boolean draw_masked = graphic_info[graphic].draw_masked;
1337 getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
1339 if (src_bitmap == NULL || width < font_width || height < font_height)
1341 ClearRectangle(drawto, dst_x, dst_y, font_width, font_height);
1345 src_x += (x == 0 ? 0 : x == xsize - 1 ? width - font_width :
1346 inner_sx + (x - 1) * font_width % inner_width);
1347 src_y += (y == 0 ? 0 : y == ysize - 1 ? height - font_height :
1348 inner_sy + (y - 1) * font_height % inner_height);
1352 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1353 dst_x - src_x, dst_y - src_y);
1354 BlitBitmapMasked(src_bitmap, drawto, src_x, src_y, font_width, font_height,
1358 BlitBitmap(src_bitmap, drawto, src_x, src_y, font_width, font_height,
1362 void AnimateEnvelope(int envelope_nr, int anim_mode, int action)
1364 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1366 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
1367 int mask_mode = (src_bitmap != NULL ? BLIT_MASKED : BLIT_ON_BACKGROUND);
1369 boolean draw_masked = graphic_info[graphic].draw_masked;
1370 int mask_mode = (draw_masked ? BLIT_MASKED : BLIT_ON_BACKGROUND);
1372 boolean ffwd_delay = (tape.playing && tape.fast_forward);
1373 boolean no_delay = (tape.warp_forward);
1374 unsigned long anim_delay = 0;
1375 int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
1376 int anim_delay_value = (no_delay ? 0 : frame_delay_value);
1377 int font_nr = FONT_ENVELOPE_1 + envelope_nr;
1378 int font_width = getFontWidth(font_nr);
1379 int font_height = getFontHeight(font_nr);
1380 int max_xsize = level.envelope_xsize[envelope_nr];
1381 int max_ysize = level.envelope_ysize[envelope_nr];
1382 int xstart = (anim_mode & ANIM_VERTICAL ? max_xsize : 0);
1383 int ystart = (anim_mode & ANIM_HORIZONTAL ? max_ysize : 0);
1384 int xend = max_xsize;
1385 int yend = (anim_mode != ANIM_DEFAULT ? max_ysize : 0);
1386 int xstep = (xstart < xend ? 1 : 0);
1387 int ystep = (ystart < yend || xstep == 0 ? 1 : 0);
1390 for (x = xstart, y = ystart; x <= xend && y <= yend; x += xstep, y += ystep)
1392 int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2;
1393 int ysize = (action == ACTION_CLOSING ? yend - (y - ystart) : y) + 2;
1394 int sx = (SXSIZE - xsize * font_width) / 2;
1395 int sy = (SYSIZE - ysize * font_height) / 2;
1398 SetDrawtoField(DRAW_BUFFERED);
1400 BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
1402 SetDrawtoField(DRAW_BACKBUFFER);
1404 for (yy = 0; yy < ysize; yy++) for (xx = 0; xx < xsize; xx++)
1405 DrawEnvelopeBackground(envelope_nr, sx,sy, xx,yy, xsize, ysize, font_nr);
1407 DrawTextToTextArea(SX + sx + font_width, SY + sy + font_height,
1408 level.envelope_text[envelope_nr], font_nr, max_xsize,
1409 xsize - 2, ysize - 2, mask_mode);
1411 redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
1414 WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
1418 void ShowEnvelope(int envelope_nr)
1420 int element = EL_ENVELOPE_1 + envelope_nr;
1421 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1422 int sound_opening = element_info[element].sound[ACTION_OPENING];
1423 int sound_closing = element_info[element].sound[ACTION_CLOSING];
1424 boolean ffwd_delay = (tape.playing && tape.fast_forward);
1425 boolean no_delay = (tape.warp_forward);
1426 int normal_delay_value = ONE_SECOND_DELAY / (ffwd_delay ? 2 : 1);
1427 int wait_delay_value = (no_delay ? 0 : normal_delay_value);
1428 int anim_mode = graphic_info[graphic].anim_mode;
1429 int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL:
1430 anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode);
1432 game.envelope_active = TRUE; /* needed for RedrawPlayfield() events */
1434 PlaySoundStereo(sound_opening, SOUND_MIDDLE);
1436 if (anim_mode == ANIM_DEFAULT)
1437 AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_OPENING);
1439 AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_OPENING);
1442 Delay(wait_delay_value);
1444 WaitForEventToContinue();
1446 PlaySoundStereo(sound_closing, SOUND_MIDDLE);
1448 if (anim_mode != ANIM_NONE)
1449 AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_CLOSING);
1451 if (anim_mode == ANIM_DEFAULT)
1452 AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_CLOSING);
1454 game.envelope_active = FALSE;
1456 SetDrawtoField(DRAW_BUFFERED);
1458 redraw_mask |= REDRAW_FIELD;
1462 void getMicroGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1464 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
1465 int mini_startx = src_bitmap->width * 3 / 4;
1466 int mini_starty = src_bitmap->height * 2 / 3;
1467 int src_x = mini_startx + graphic_info[graphic].src_x / 8;
1468 int src_y = mini_starty + graphic_info[graphic].src_y / 8;
1470 *bitmap = src_bitmap;
1475 void DrawMicroElement(int xpos, int ypos, int element)
1479 int graphic = el2preimg(element);
1481 getMicroGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1482 BlitBitmap(src_bitmap, drawto, src_x, src_y, MICRO_TILEX, MICRO_TILEY,
1490 SetDrawBackgroundMask(REDRAW_NONE);
1493 for (x = BX1; x <= BX2; x++)
1494 for (y = BY1; y <= BY2; y++)
1495 DrawScreenField(x, y);
1497 redraw_mask |= REDRAW_FIELD;
1500 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1504 for (x = 0; x < size_x; x++)
1505 for (y = 0; y < size_y; y++)
1506 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1508 redraw_mask |= REDRAW_FIELD;
1511 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1515 DrawBackground(xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
1517 if (lev_fieldx < STD_LEV_FIELDX)
1518 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1519 if (lev_fieldy < STD_LEV_FIELDY)
1520 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1522 xpos += MICRO_TILEX;
1523 ypos += MICRO_TILEY;
1525 for (x = -1; x <= STD_LEV_FIELDX; x++)
1527 for (y = -1; y <= STD_LEV_FIELDY; y++)
1529 int lx = from_x + x, ly = from_y + y;
1531 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1532 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1533 level.field[lx][ly]);
1534 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1
1535 && BorderElement != EL_EMPTY)
1536 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1537 getBorderElement(lx, ly));
1541 redraw_mask |= REDRAW_MICROLEVEL;
1544 #define MICROLABEL_EMPTY 0
1545 #define MICROLABEL_LEVEL_NAME 1
1546 #define MICROLABEL_CREATED_BY 2
1547 #define MICROLABEL_LEVEL_AUTHOR 3
1548 #define MICROLABEL_IMPORTED_FROM 4
1549 #define MICROLABEL_LEVEL_IMPORT_INFO 5
1551 static void DrawMicroLevelLabelExt(int mode)
1553 char label_text[MAX_OUTPUT_LINESIZE + 1];
1554 int max_len_label_text;
1555 int font_nr = FONT_TEXT_2;
1557 if (mode == MICROLABEL_CREATED_BY || mode == MICROLABEL_IMPORTED_FROM)
1558 font_nr = FONT_TEXT_3;
1560 max_len_label_text = SXSIZE / getFontWidth(font_nr);
1562 DrawBackground(SX, MICROLABEL_YPOS, SXSIZE, getFontHeight(font_nr));
1564 strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
1565 mode == MICROLABEL_CREATED_BY ? "created by" :
1566 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
1567 mode == MICROLABEL_IMPORTED_FROM ? "imported from" :
1568 mode == MICROLABEL_LEVEL_IMPORT_INFO ?
1569 leveldir_current->imported_from : ""),
1570 max_len_label_text);
1571 label_text[max_len_label_text] = '\0';
1573 if (strlen(label_text) > 0)
1575 int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
1576 int lypos = MICROLABEL_YPOS;
1578 DrawText(lxpos, lypos, label_text, font_nr);
1581 redraw_mask |= REDRAW_MICROLEVEL;
1584 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1586 static unsigned long scroll_delay = 0;
1587 static unsigned long label_delay = 0;
1588 static int from_x, from_y, scroll_direction;
1589 static int label_state, label_counter;
1590 int last_game_status = game_status; /* save current game status */
1592 /* force PREVIEW font on preview level */
1593 game_status = GAME_MODE_PSEUDO_PREVIEW;
1597 from_x = from_y = 0;
1598 scroll_direction = MV_RIGHT;
1602 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1603 DrawMicroLevelLabelExt(label_state);
1605 /* initialize delay counters */
1606 DelayReached(&scroll_delay, 0);
1607 DelayReached(&label_delay, 0);
1609 if (leveldir_current->name)
1611 int text_width = getTextWidth(leveldir_current->name, FONT_TEXT_1);
1612 int lxpos = SX + (SXSIZE - text_width) / 2;
1613 int lypos = SY + 352;
1615 DrawText(lxpos, lypos, leveldir_current->name, FONT_TEXT_1);
1618 game_status = last_game_status; /* restore current game status */
1623 /* scroll micro level, if needed */
1624 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1625 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1627 switch (scroll_direction)
1633 scroll_direction = MV_UP;
1637 if (from_x < lev_fieldx - STD_LEV_FIELDX)
1640 scroll_direction = MV_DOWN;
1647 scroll_direction = MV_RIGHT;
1651 if (from_y < lev_fieldy - STD_LEV_FIELDY)
1654 scroll_direction = MV_LEFT;
1661 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1664 /* redraw micro level label, if needed */
1665 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1666 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1667 strcmp(level.author, leveldir_current->name) != 0 &&
1668 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1670 int max_label_counter = 23;
1672 if (leveldir_current->imported_from != NULL)
1673 max_label_counter += 14;
1675 label_counter = (label_counter + 1) % max_label_counter;
1676 label_state = (label_counter >= 0 && label_counter <= 7 ?
1677 MICROLABEL_LEVEL_NAME :
1678 label_counter >= 9 && label_counter <= 12 ?
1679 MICROLABEL_CREATED_BY :
1680 label_counter >= 14 && label_counter <= 21 ?
1681 MICROLABEL_LEVEL_AUTHOR :
1682 label_counter >= 23 && label_counter <= 26 ?
1683 MICROLABEL_IMPORTED_FROM :
1684 label_counter >= 28 && label_counter <= 35 ?
1685 MICROLABEL_LEVEL_IMPORT_INFO : MICROLABEL_EMPTY);
1686 DrawMicroLevelLabelExt(label_state);
1689 game_status = last_game_status; /* restore current game status */
1692 inline void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
1693 int graphic, int sync_frame, int mask_mode)
1695 int frame = getGraphicAnimationFrame(graphic, sync_frame);
1697 if (mask_mode == USE_MASKING)
1698 DrawGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
1700 DrawGraphicExt(dst_bitmap, x, y, graphic, frame);
1703 inline void DrawGraphicAnimation(int x, int y, int graphic)
1705 int lx = LEVELX(x), ly = LEVELY(y);
1707 if (!IN_SCR_FIELD(x, y))
1710 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
1711 graphic, GfxFrame[lx][ly], NO_MASKING);
1712 MarkTileDirty(x, y);
1715 void DrawLevelGraphicAnimation(int x, int y, int graphic)
1717 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
1720 void DrawLevelElementAnimation(int x, int y, int element)
1723 int graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
1725 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
1727 DrawGraphicAnimation(SCREENX(x), SCREENY(y), el2img(element));
1731 inline void DrawLevelGraphicAnimationIfNeeded(int x, int y, int graphic)
1733 int sx = SCREENX(x), sy = SCREENY(y);
1735 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
1738 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
1741 DrawGraphicAnimation(sx, sy, graphic);
1743 if (GFX_CRUMBLED(Feld[x][y]))
1744 DrawLevelFieldCrumbledSand(x, y);
1747 void DrawLevelElementAnimationIfNeeded(int x, int y, int element)
1749 int sx = SCREENX(x), sy = SCREENY(y);
1752 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
1755 graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
1757 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
1760 DrawGraphicAnimation(sx, sy, graphic);
1762 if (GFX_CRUMBLED(element))
1763 DrawLevelFieldCrumbledSand(x, y);
1766 static int getPlayerGraphic(struct PlayerInfo *player, int move_dir)
1768 if (player->use_murphy_graphic)
1770 /* this works only because currently only one player can be "murphy" ... */
1771 static int last_horizontal_dir = MV_LEFT;
1772 int graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, move_dir);
1774 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
1775 last_horizontal_dir = move_dir;
1777 if (graphic == IMG_SP_MURPHY) /* undefined => use special graphic */
1779 int direction = (player->is_snapping ? move_dir : last_horizontal_dir);
1781 graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, direction);
1787 return el_act_dir2img(player->element_nr, player->GfxAction, move_dir);
1790 static boolean equalGraphics(int graphic1, int graphic2)
1792 struct GraphicInfo *g1 = &graphic_info[graphic1];
1793 struct GraphicInfo *g2 = &graphic_info[graphic2];
1795 return (g1->bitmap == g2->bitmap &&
1796 g1->src_x == g2->src_x &&
1797 g1->src_y == g2->src_y &&
1798 g1->anim_frames == g2->anim_frames &&
1799 g1->anim_delay == g2->anim_delay &&
1800 g1->anim_mode == g2->anim_mode);
1803 void DrawAllPlayers()
1807 for (i = 0; i < MAX_PLAYERS; i++)
1808 if (stored_player[i].active)
1809 DrawPlayer(&stored_player[i]);
1812 void DrawPlayerField(int x, int y)
1814 if (!IS_PLAYER(x, y))
1817 DrawPlayer(PLAYERINFO(x, y));
1820 void DrawPlayer(struct PlayerInfo *player)
1822 int jx = player->jx;
1823 int jy = player->jy;
1824 int move_dir = player->MovDir;
1826 int last_jx = player->last_jx;
1827 int last_jy = player->last_jy;
1828 int next_jx = jx + (jx - last_jx);
1829 int next_jy = jy + (jy - last_jy);
1830 boolean player_is_moving = (last_jx != jx || last_jy != jy ? TRUE : FALSE);
1832 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? +1 : 0);
1833 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? +1 : 0);
1834 int last_jx = (player->is_moving ? jx - dx : jx);
1835 int last_jy = (player->is_moving ? jy - dy : jy);
1836 int next_jx = jx + dx;
1837 int next_jy = jy + dy;
1838 boolean player_is_moving = (player->MovPos ? TRUE : FALSE);
1840 int sx = SCREENX(jx), sy = SCREENY(jy);
1841 int sxx = 0, syy = 0;
1842 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
1844 int action = ACTION_DEFAULT;
1845 int last_player_graphic = getPlayerGraphic(player, move_dir);
1846 int last_player_frame = player->Frame;
1849 if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
1853 if (!IN_LEV_FIELD(jx, jy))
1855 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
1856 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
1857 printf("DrawPlayerField(): This should never happen!\n");
1862 if (element == EL_EXPLOSION)
1865 action = (player->is_pushing ? ACTION_PUSHING :
1866 player->is_digging ? ACTION_DIGGING :
1867 player->is_collecting ? ACTION_COLLECTING :
1868 player->is_moving ? ACTION_MOVING :
1869 player->is_snapping ? ACTION_SNAPPING :
1870 player->is_dropping ? ACTION_DROPPING :
1871 player->is_waiting ? player->action_waiting : ACTION_DEFAULT);
1873 InitPlayerGfxAnimation(player, action, move_dir);
1875 /* ----------------------------------------------------------------------- */
1876 /* draw things in the field the player is leaving, if needed */
1877 /* ----------------------------------------------------------------------- */
1880 if (player->is_moving)
1882 if (player_is_moving)
1885 if (Back[last_jx][last_jy] && IS_DRAWABLE(last_element))
1887 DrawLevelElement(last_jx, last_jy, Back[last_jx][last_jy]);
1889 if (last_element == EL_DYNAMITE_ACTIVE ||
1890 last_element == EL_SP_DISK_RED_ACTIVE)
1891 DrawDynamite(last_jx, last_jy);
1893 DrawLevelFieldThruMask(last_jx, last_jy);
1895 else if (last_element == EL_DYNAMITE_ACTIVE ||
1896 last_element == EL_SP_DISK_RED_ACTIVE)
1897 DrawDynamite(last_jx, last_jy);
1899 DrawLevelField(last_jx, last_jy);
1901 if (player->is_pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
1902 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
1905 if (!IN_SCR_FIELD(sx, sy))
1908 if (setup.direct_draw)
1909 SetDrawtoField(DRAW_BUFFERED);
1911 /* ----------------------------------------------------------------------- */
1912 /* draw things behind the player, if needed */
1913 /* ----------------------------------------------------------------------- */
1916 DrawLevelElement(jx, jy, Back[jx][jy]);
1917 else if (IS_ACTIVE_BOMB(element))
1918 DrawLevelElement(jx, jy, EL_EMPTY);
1921 if (player_is_moving && GfxElement[jx][jy] != EL_UNDEFINED)
1923 if (GFX_CRUMBLED(GfxElement[jx][jy]))
1924 DrawLevelFieldCrumbledSandDigging(jx, jy, move_dir, player->StepFrame);
1927 int old_element = GfxElement[jx][jy];
1928 int old_graphic = el_act_dir2img(old_element, action, move_dir);
1929 int frame = getGraphicAnimationFrame(old_graphic, player->StepFrame);
1931 DrawGraphic(sx, sy, old_graphic, frame);
1936 GfxElement[jx][jy] = EL_UNDEFINED;
1938 DrawLevelField(jx, jy);
1942 /* ----------------------------------------------------------------------- */
1943 /* draw player himself */
1944 /* ----------------------------------------------------------------------- */
1948 graphic = getPlayerGraphic(player, move_dir);
1950 /* in the case of changed player action or direction, prevent the current
1951 animation frame from being restarted for identical animations */
1952 if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic))
1953 player->Frame = last_player_frame;
1957 if (player->use_murphy_graphic)
1959 static int last_horizontal_dir = MV_LEFT;
1961 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
1962 last_horizontal_dir = move_dir;
1964 graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, move_dir);
1966 if (graphic == IMG_SP_MURPHY) /* undefined => use special graphic */
1968 int direction = (player->is_snapping ? move_dir : last_horizontal_dir);
1970 graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, direction);
1974 graphic = el_act_dir2img(player->element_nr, player->GfxAction, move_dir);
1978 frame = getGraphicAnimationFrame(graphic, player->Frame);
1982 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
1983 sxx = player->GfxPos;
1985 syy = player->GfxPos;
1988 if (!setup.soft_scrolling && ScreenMovPos)
1991 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
1993 if (SHIELD_ON(player))
1995 int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
1996 IMG_SHIELD_NORMAL_ACTIVE);
1997 int frame = getGraphicAnimationFrame(graphic, -1);
1999 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
2002 /* ----------------------------------------------------------------------- */
2003 /* draw things the player is pushing, if needed */
2004 /* ----------------------------------------------------------------------- */
2007 printf("::: %d, %d [%d, %d] [%d]\n",
2008 player->is_pushing, player_is_moving, player->GfxAction,
2009 player->is_moving, player_is_moving);
2013 if (player->is_pushing && player->is_moving)
2015 if (player->is_pushing && player_is_moving)
2019 int px = SCREENX(jx), py = SCREENY(jy);
2020 int pxx = (TILEX - ABS(sxx)) * dx;
2021 int pyy = (TILEY - ABS(syy)) * dy;
2023 int px = SCREENX(next_jx), py = SCREENY(next_jy);
2032 if (!IS_MOVING(jx, jy)) /* push movement already finished */
2033 element = Feld[next_jx][next_jy];
2035 graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
2036 frame = getGraphicAnimationFrame(graphic, player->StepFrame);
2038 /* draw background element under pushed element (like the Sokoban field) */
2039 if (Back[next_jx][next_jy])
2040 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
2042 /* masked drawing is needed for EMC style (double) movement graphics */
2043 DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame, NO_CUTTING);
2046 if (Back[next_jx][next_jy])
2047 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
2049 if ((pxx || pyy) && element == EL_SOKOBAN_OBJECT)
2050 DrawGraphicShiftedThruMask(px, py, pxx, pyy, IMG_SOKOBAN_OBJECT, 0,
2054 int element = MovingOrBlocked2Element(next_jx, next_jy);
2055 int graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
2057 int frame = getGraphicAnimationFrame(graphic, player->StepFrame);
2059 int frame = getGraphicAnimationFrame(graphic, player->Frame);
2063 /* masked drawing is needed for EMC style (double) movement graphics */
2064 DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame,
2067 DrawGraphicShifted(px, py, pxx, pyy, graphic, frame,
2068 NO_CUTTING, NO_MASKING);
2074 /* ----------------------------------------------------------------------- */
2075 /* draw things in front of player (active dynamite or dynabombs) */
2076 /* ----------------------------------------------------------------------- */
2078 if (IS_ACTIVE_BOMB(element))
2080 graphic = el2img(element);
2081 frame = getGraphicAnimationFrame(graphic, GfxFrame[jx][jy]);
2083 if (game.emulation == EMU_SUPAPLEX)
2084 DrawGraphic(sx, sy, IMG_SP_DISK_RED, frame);
2086 DrawGraphicThruMask(sx, sy, graphic, frame);
2089 if (player_is_moving && last_element == EL_EXPLOSION)
2091 int graphic = el_act2img(GfxElement[last_jx][last_jy], ACTION_EXPLODING);
2092 int delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2);
2093 int phase = ExplodePhase[last_jx][last_jy] - 1;
2094 int frame = getGraphicAnimationFrame(graphic, phase - delay);
2097 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy), graphic, frame);
2100 /* ----------------------------------------------------------------------- */
2101 /* draw elements the player is just walking/passing through/under */
2102 /* ----------------------------------------------------------------------- */
2104 if (player_is_moving)
2106 /* handle the field the player is leaving ... */
2107 if (IS_ACCESSIBLE_INSIDE(last_element))
2108 DrawLevelField(last_jx, last_jy);
2109 else if (IS_ACCESSIBLE_UNDER(last_element))
2110 DrawLevelFieldThruMask(last_jx, last_jy);
2114 /* do not redraw accessible elements if the player is just pushing them */
2115 if (!player_is_moving || !player->is_pushing)
2117 /* ... and the field the player is entering */
2118 if (IS_ACCESSIBLE_INSIDE(element))
2119 DrawLevelField(jx, jy);
2120 else if (IS_ACCESSIBLE_UNDER(element))
2121 DrawLevelFieldThruMask(jx, jy);
2127 /* !!! I have forgotton what this should be good for !!! */
2128 /* !!! causes player being visible when pushing from within tubes !!! */
2129 if (!player->is_pushing)
2132 /* ... and the field the player is entering */
2133 if (IS_ACCESSIBLE_INSIDE(element))
2134 DrawLevelField(jx, jy);
2135 else if (IS_ACCESSIBLE_UNDER(element))
2136 DrawLevelFieldThruMask(jx, jy);
2140 if (setup.direct_draw)
2142 int dst_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
2143 int dst_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
2144 int x_size = TILEX * (1 + ABS(jx - last_jx));
2145 int y_size = TILEY * (1 + ABS(jy - last_jy));
2147 BlitBitmap(drawto_field, window,
2148 dst_x, dst_y, x_size, y_size, dst_x, dst_y);
2149 SetDrawtoField(DRAW_DIRECT);
2152 MarkTileDirty(sx, sy);
2155 /* ------------------------------------------------------------------------- */
2157 void WaitForEventToContinue()
2159 boolean still_wait = TRUE;
2161 /* simulate releasing mouse button over last gadget, if still pressed */
2163 HandleGadgets(-1, -1, 0);
2165 button_status = MB_RELEASED;
2177 case EVENT_BUTTONPRESS:
2178 case EVENT_KEYPRESS:
2182 case EVENT_KEYRELEASE:
2183 ClearPlayerAction();
2187 HandleOtherEvents(&event);
2191 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2198 /* don't eat all CPU time */
2203 #define MAX_REQUEST_LINES 13
2204 #define MAX_REQUEST_LINE_FONT1_LEN 7
2205 #define MAX_REQUEST_LINE_FONT2_LEN 10
2207 boolean Request(char *text, unsigned int req_state)
2209 int mx, my, ty, result = -1;
2210 unsigned int old_door_state;
2211 int last_game_status = game_status; /* save current game status */
2212 int max_request_line_len = MAX_REQUEST_LINE_FONT1_LEN;
2213 int font_nr = FONT_TEXT_2;
2214 int max_word_len = 0;
2217 for (text_ptr = text; *text_ptr; text_ptr++)
2219 max_word_len = (*text_ptr != ' ' ? max_word_len + 1 : 0);
2221 if (max_word_len > MAX_REQUEST_LINE_FONT1_LEN)
2223 max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
2224 font_nr = FONT_LEVEL_NUMBER;
2231 if (game_status == GAME_MODE_PLAYING &&
2232 level.game_engine_type == GAME_ENGINE_TYPE_EM)
2233 BlitScreenToBitmap_EM(backbuffer);
2237 /* disable deactivated drawing when quick-loading level tape recording */
2238 if (tape.playing && tape.deactivate_display)
2239 TapeDeactivateDisplayOff(TRUE);
2243 SetMouseCursor(CURSOR_DEFAULT);
2246 #if defined(NETWORK_AVALIABLE)
2247 /* pause network game while waiting for request to answer */
2248 if (options.network &&
2249 game_status == GAME_MODE_PLAYING &&
2250 req_state & REQUEST_WAIT_FOR_INPUT)
2251 SendToServer_PausePlaying();
2254 old_door_state = GetDoorState();
2256 /* simulate releasing mouse button over last gadget, if still pressed */
2258 HandleGadgets(-1, -1, 0);
2262 if (old_door_state & DOOR_OPEN_1)
2264 CloseDoor(DOOR_CLOSE_1);
2266 /* save old door content */
2267 BlitBitmap(bitmap_db_door, bitmap_db_door,
2268 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
2269 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
2272 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
2274 /* clear door drawing field */
2275 DrawBackground(DX, DY, DXSIZE, DYSIZE);
2277 /* force DOOR font on preview level */
2278 game_status = GAME_MODE_PSEUDO_DOOR;
2280 /* write text for request */
2281 for (ty = 0; ty < MAX_REQUEST_LINES; ty++)
2283 char text_line[max_request_line_len + 1];
2289 for (tl = 0, tx = 0; tx < max_request_line_len; tl++, tx++)
2292 if (!tc || tc == ' ')
2303 strncpy(text_line, text, tl);
2306 DrawText(DX + (DXSIZE - tl * getFontWidth(font_nr)) / 2,
2307 DY + 8 + ty * (getFontHeight(font_nr) + 2),
2308 text_line, font_nr);
2310 text += tl + (tc == ' ' ? 1 : 0);
2313 game_status = last_game_status; /* restore current game status */
2315 if (req_state & REQ_ASK)
2317 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
2318 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
2320 else if (req_state & REQ_CONFIRM)
2322 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
2324 else if (req_state & REQ_PLAYER)
2326 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
2327 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
2328 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
2329 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
2332 /* copy request gadgets to door backbuffer */
2333 BlitBitmap(drawto, bitmap_db_door,
2334 DX, DY, DXSIZE, DYSIZE,
2335 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2337 OpenDoor(DOOR_OPEN_1);
2343 if (!(req_state & REQUEST_WAIT_FOR_INPUT))
2345 SetDrawBackgroundMask(REDRAW_FIELD);
2350 if (game_status != GAME_MODE_MAIN)
2353 button_status = MB_RELEASED;
2355 request_gadget_id = -1;
2357 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
2360 SetMouseCursor(CURSOR_DEFAULT);
2373 case EVENT_BUTTONPRESS:
2374 case EVENT_BUTTONRELEASE:
2375 case EVENT_MOTIONNOTIFY:
2377 if (event.type == EVENT_MOTIONNOTIFY)
2379 if (!PointerInWindow(window))
2380 continue; /* window and pointer are on different screens */
2385 motion_status = TRUE;
2386 mx = ((MotionEvent *) &event)->x;
2387 my = ((MotionEvent *) &event)->y;
2391 motion_status = FALSE;
2392 mx = ((ButtonEvent *) &event)->x;
2393 my = ((ButtonEvent *) &event)->y;
2394 if (event.type == EVENT_BUTTONPRESS)
2395 button_status = ((ButtonEvent *) &event)->button;
2397 button_status = MB_RELEASED;
2400 /* this sets 'request_gadget_id' */
2401 HandleGadgets(mx, my, button_status);
2403 switch(request_gadget_id)
2405 case TOOL_CTRL_ID_YES:
2408 case TOOL_CTRL_ID_NO:
2411 case TOOL_CTRL_ID_CONFIRM:
2412 result = TRUE | FALSE;
2415 case TOOL_CTRL_ID_PLAYER_1:
2418 case TOOL_CTRL_ID_PLAYER_2:
2421 case TOOL_CTRL_ID_PLAYER_3:
2424 case TOOL_CTRL_ID_PLAYER_4:
2435 case EVENT_KEYPRESS:
2436 switch(GetEventKey((KeyEvent *)&event, TRUE))
2449 if (req_state & REQ_PLAYER)
2453 case EVENT_KEYRELEASE:
2454 ClearPlayerAction();
2458 HandleOtherEvents(&event);
2462 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2464 int joy = AnyJoystick();
2466 if (joy & JOY_BUTTON_1)
2468 else if (joy & JOY_BUTTON_2)
2474 /* don't eat all CPU time */
2478 if (game_status != GAME_MODE_MAIN)
2483 if (!(req_state & REQ_STAY_OPEN))
2485 CloseDoor(DOOR_CLOSE_1);
2487 if (((old_door_state & DOOR_OPEN_1) && !(req_state & REQ_STAY_CLOSED)) ||
2488 (req_state & REQ_REOPEN))
2489 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
2494 SetDrawBackgroundMask(REDRAW_FIELD);
2496 #if defined(NETWORK_AVALIABLE)
2497 /* continue network game after request */
2498 if (options.network &&
2499 game_status == GAME_MODE_PLAYING &&
2500 req_state & REQUEST_WAIT_FOR_INPUT)
2501 SendToServer_ContinuePlaying();
2505 /* restore deactivated drawing when quick-loading level tape recording */
2506 if (tape.playing && tape.deactivate_display)
2507 TapeDeactivateDisplayOn();
2513 unsigned int OpenDoor(unsigned int door_state)
2515 if (door_state & DOOR_COPY_BACK)
2517 if (door_state & DOOR_OPEN_1)
2518 BlitBitmap(bitmap_db_door, bitmap_db_door,
2519 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
2520 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2522 if (door_state & DOOR_OPEN_2)
2523 BlitBitmap(bitmap_db_door, bitmap_db_door,
2524 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY2, VXSIZE, VYSIZE,
2525 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2527 door_state &= ~DOOR_COPY_BACK;
2530 return MoveDoor(door_state);
2533 unsigned int CloseDoor(unsigned int door_state)
2535 unsigned int old_door_state = GetDoorState();
2537 if (!(door_state & DOOR_NO_COPY_BACK))
2539 if (old_door_state & DOOR_OPEN_1)
2540 BlitBitmap(backbuffer, bitmap_db_door,
2541 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2543 if (old_door_state & DOOR_OPEN_2)
2544 BlitBitmap(backbuffer, bitmap_db_door,
2545 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2547 door_state &= ~DOOR_NO_COPY_BACK;
2550 return MoveDoor(door_state);
2553 unsigned int GetDoorState()
2555 return MoveDoor(DOOR_GET_STATE);
2558 unsigned int SetDoorState(unsigned int door_state)
2560 return MoveDoor(door_state | DOOR_SET_STATE);
2563 unsigned int MoveDoor(unsigned int door_state)
2565 static int door1 = DOOR_OPEN_1;
2566 static int door2 = DOOR_CLOSE_2;
2567 unsigned long door_delay = 0;
2568 unsigned long door_delay_value;
2571 if (door_state == DOOR_GET_STATE)
2572 return(door1 | door2);
2574 if (door_state & DOOR_SET_STATE)
2576 if (door_state & DOOR_ACTION_1)
2577 door1 = door_state & DOOR_ACTION_1;
2578 if (door_state & DOOR_ACTION_2)
2579 door2 = door_state & DOOR_ACTION_2;
2581 return(door1 | door2);
2584 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2585 door_state &= ~DOOR_OPEN_1;
2586 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2587 door_state &= ~DOOR_CLOSE_1;
2588 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2589 door_state &= ~DOOR_OPEN_2;
2590 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2591 door_state &= ~DOOR_CLOSE_2;
2593 door_delay_value = (door_state & DOOR_ACTION_1 ? door_1.step_delay :
2596 if (setup.quick_doors)
2598 stepsize = 20; /* must be choosen to always draw last frame */
2599 door_delay_value = 0;
2602 StopSound(SND_DOOR_OPENING);
2603 StopSound(SND_DOOR_CLOSING);
2607 if (global.autoplay_leveldir)
2609 door_state |= DOOR_NO_DELAY;
2610 door_state &= ~DOOR_CLOSE_ALL;
2613 if (door_state & DOOR_ACTION)
2615 boolean door_1_done = !(door_state & DOOR_ACTION_1);
2616 boolean door_2_done = !(door_state & DOOR_ACTION_2);
2617 int start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2618 int end = (door_state & DOOR_ACTION_1 &&
2619 door_1.anim_mode == ANIM_VERTICAL ? DYSIZE : DXSIZE);
2622 if (!(door_state & DOOR_NO_DELAY) && !setup.quick_doors)
2624 /* opening door sound has priority over simultaneously closing door */
2625 if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
2626 PlaySoundStereo(SND_DOOR_OPENING, SOUND_MIDDLE);
2627 else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
2628 PlaySoundStereo(SND_DOOR_CLOSING, SOUND_MIDDLE);
2631 for (x = start; x <= end && !(door_1_done && door_2_done); x += stepsize)
2633 Bitmap *bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2634 GC gc = bitmap->stored_clip_gc;
2636 if (door_state & DOOR_ACTION_1)
2638 int a = MIN(x * door_1.step_offset, end);
2639 int i = (door_state & DOOR_OPEN_1 ? end - a : a);
2643 BlitBitmap(bitmap_db_door, drawto,
2644 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i / 2,
2645 DXSIZE, DYSIZE - i / 2, DX, DY);
2647 ClearRectangle(drawto, DX, DY + DYSIZE - i / 2, DXSIZE, i / 2);
2650 if (door_1.anim_mode == ANIM_HORIZONTAL && x <= DXSIZE)
2652 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
2653 int dst1_x = DX + DXSIZE - i, dst1_y = DY;
2654 int src2_x = DXSIZE - i, src2_y = DOOR_GFX_PAGEY1;
2655 int dst2_x = DX, dst2_y = DY;
2656 int width = i, height = DYSIZE;
2658 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2659 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2662 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2663 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2666 else if (door_1.anim_mode == ANIM_VERTICAL && x <= DYSIZE)
2668 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
2669 int dst1_x = DX, dst1_y = DY + DYSIZE - i;
2670 int src2_x = 0, src2_y = DOOR_GFX_PAGEY1 + DYSIZE - i;
2671 int dst2_x = DX, dst2_y = DY;
2672 int width = DXSIZE, height = i;
2674 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2675 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2678 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2679 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2682 else if (x <= DXSIZE) /* ANIM_DEFAULT */
2684 int j = (door_1.anim_mode == ANIM_DEFAULT ? (DXSIZE - i) / 3 : 0);
2686 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2687 BlitBitmapMasked(bitmap, drawto,
2688 DXSIZE, DOOR_GFX_PAGEY1, i, 77,
2689 DX + DXSIZE - i, DY + j);
2690 BlitBitmapMasked(bitmap, drawto,
2691 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
2692 DX + DXSIZE - i, DY + 140 + j);
2693 SetClipOrigin(bitmap, gc, DX - DXSIZE + i,
2694 DY - (DOOR_GFX_PAGEY1 + j));
2695 BlitBitmapMasked(bitmap, drawto,
2696 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
2698 BlitBitmapMasked(bitmap, drawto,
2699 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
2702 BlitBitmapMasked(bitmap, drawto,
2703 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2705 BlitBitmapMasked(bitmap, drawto,
2706 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2708 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2709 BlitBitmapMasked(bitmap, drawto,
2710 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2711 DX + DXSIZE - i, DY + 77 + j);
2712 BlitBitmapMasked(bitmap, drawto,
2713 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2714 DX + DXSIZE - i, DY + 203 + j);
2717 redraw_mask |= REDRAW_DOOR_1;
2718 door_1_done = (a == end);
2721 if (door_state & DOOR_ACTION_2)
2723 int a = MIN(x * door_2.step_offset, VXSIZE);
2724 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - a : a);
2728 BlitBitmap(bitmap_db_door, drawto,
2729 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i / 2,
2730 VXSIZE, VYSIZE - i / 2, VX, VY);
2732 ClearRectangle(drawto, VX, VY + VYSIZE - i / 2, VXSIZE, i / 2);
2735 if (door_2.anim_mode == ANIM_HORIZONTAL && x <= VXSIZE)
2737 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
2738 int dst1_x = VX + VXSIZE - i, dst1_y = VY;
2739 int src2_x = VXSIZE - i, src2_y = DOOR_GFX_PAGEY2;
2740 int dst2_x = VX, dst2_y = VY;
2741 int width = i, height = VYSIZE;
2743 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2744 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2747 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2748 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2751 else if (door_2.anim_mode == ANIM_VERTICAL && x <= VYSIZE)
2753 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
2754 int dst1_x = VX, dst1_y = VY + VYSIZE - i;
2755 int src2_x = 0, src2_y = DOOR_GFX_PAGEY2 + VYSIZE - i;
2756 int dst2_x = VX, dst2_y = VY;
2757 int width = VXSIZE, height = i;
2759 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2760 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2763 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2764 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2767 else if (x <= VXSIZE) /* ANIM_DEFAULT */
2769 int j = (door_2.anim_mode == ANIM_DEFAULT ? (VXSIZE - i) / 3 : 0);
2771 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2772 BlitBitmapMasked(bitmap, drawto,
2773 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
2774 VX + VXSIZE - i, VY + j);
2775 SetClipOrigin(bitmap, gc,
2776 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2777 BlitBitmapMasked(bitmap, drawto,
2778 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
2781 BlitBitmapMasked(bitmap, drawto,
2782 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2783 i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
2784 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2785 BlitBitmapMasked(bitmap, drawto,
2786 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2788 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2791 redraw_mask |= REDRAW_DOOR_2;
2792 door_2_done = (a == VXSIZE);
2797 if (game_status == GAME_MODE_MAIN)
2800 if (!(door_state & DOOR_NO_DELAY))
2801 WaitUntilDelayReached(&door_delay, door_delay_value);
2806 if (setup.quick_doors)
2808 StopSound(SND_DOOR_OPENING);
2809 StopSound(SND_DOOR_CLOSING);
2813 if (door_state & DOOR_ACTION_1)
2814 door1 = door_state & DOOR_ACTION_1;
2815 if (door_state & DOOR_ACTION_2)
2816 door2 = door_state & DOOR_ACTION_2;
2818 return (door1 | door2);
2821 void DrawSpecialEditorDoor()
2823 /* draw bigger toolbox window */
2824 BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
2825 DOOR_GFX_PAGEX7, 0, EXSIZE + 8, 8,
2827 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2828 EX - 4, VY - 4, EXSIZE + 8, EYSIZE - VYSIZE + 4,
2831 redraw_mask |= REDRAW_ALL;
2834 void UndrawSpecialEditorDoor()
2836 /* draw normal tape recorder window */
2837 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2838 EX - 4, EY - 12, EXSIZE + 8, EYSIZE - VYSIZE + 12,
2841 redraw_mask |= REDRAW_ALL;
2845 /* ---------- new tool button stuff ---------------------------------------- */
2847 /* graphic position values for tool buttons */
2848 #define TOOL_BUTTON_YES_XPOS 2
2849 #define TOOL_BUTTON_YES_YPOS 250
2850 #define TOOL_BUTTON_YES_GFX_YPOS 0
2851 #define TOOL_BUTTON_YES_XSIZE 46
2852 #define TOOL_BUTTON_YES_YSIZE 28
2853 #define TOOL_BUTTON_NO_XPOS 52
2854 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2855 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2856 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2857 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2858 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2859 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2860 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2861 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2862 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2863 #define TOOL_BUTTON_PLAYER_XSIZE 30
2864 #define TOOL_BUTTON_PLAYER_YSIZE 30
2865 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2866 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2867 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2868 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2869 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2870 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2871 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2872 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2873 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2874 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2875 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2876 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2877 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2878 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2879 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2880 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2881 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2882 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2883 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2884 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2893 } toolbutton_info[NUM_TOOL_BUTTONS] =
2896 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2897 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2898 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2903 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2904 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2905 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2910 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2911 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2912 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2913 TOOL_CTRL_ID_CONFIRM,
2917 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2918 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2919 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2920 TOOL_CTRL_ID_PLAYER_1,
2924 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2925 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2926 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2927 TOOL_CTRL_ID_PLAYER_2,
2931 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2932 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2933 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2934 TOOL_CTRL_ID_PLAYER_3,
2938 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2939 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2940 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2941 TOOL_CTRL_ID_PLAYER_4,
2946 void CreateToolButtons()
2950 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2952 Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2953 Bitmap *deco_bitmap = None;
2954 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2955 struct GadgetInfo *gi;
2956 unsigned long event_mask;
2957 int gd_xoffset, gd_yoffset;
2958 int gd_x1, gd_x2, gd_y;
2961 event_mask = GD_EVENT_RELEASED;
2963 gd_xoffset = toolbutton_info[i].xpos;
2964 gd_yoffset = toolbutton_info[i].ypos;
2965 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2966 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2967 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2969 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2971 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
2973 getMiniGraphicSource(PLAYER_NR_GFX(IMG_PLAYER_1, player_nr),
2974 &deco_bitmap, &deco_x, &deco_y);
2975 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2976 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2979 gi = CreateGadget(GDI_CUSTOM_ID, id,
2980 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2981 GDI_X, DX + toolbutton_info[i].x,
2982 GDI_Y, DY + toolbutton_info[i].y,
2983 GDI_WIDTH, toolbutton_info[i].width,
2984 GDI_HEIGHT, toolbutton_info[i].height,
2985 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2986 GDI_STATE, GD_BUTTON_UNPRESSED,
2987 GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
2988 GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
2989 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
2990 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2991 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2992 GDI_DECORATION_SHIFTING, 1, 1,
2993 GDI_EVENT_MASK, event_mask,
2994 GDI_CALLBACK_ACTION, HandleToolButtons,
2998 Error(ERR_EXIT, "cannot create gadget");
3000 tool_gadget[id] = gi;
3004 void FreeToolButtons()
3008 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
3009 FreeGadget(tool_gadget[i]);
3012 static void UnmapToolButtons()
3016 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
3017 UnmapGadget(tool_gadget[i]);
3020 static void HandleToolButtons(struct GadgetInfo *gi)
3022 request_gadget_id = gi->custom_id;
3027 static struct Mapping_EM_to_RND_object
3030 boolean is_rnd_to_em_mapping; /* unique mapping EM <-> RND */
3031 boolean is_backside; /* backside of moving element */
3037 em_object_mapping_list[] =
3040 Xblank, TRUE, FALSE,
3044 Yacid_splash_eB, FALSE, FALSE,
3045 EL_ACID_SPLASH_RIGHT, -1, -1
3048 Yacid_splash_wB, FALSE, FALSE,
3049 EL_ACID_SPLASH_LEFT, -1, -1
3052 #ifdef EM_ENGINE_BAD_ROLL
3054 Xstone_force_e, FALSE, FALSE,
3055 EL_ROCK, -1, MV_BIT_RIGHT
3058 Xstone_force_w, FALSE, FALSE,
3059 EL_ROCK, -1, MV_BIT_LEFT
3062 Xnut_force_e, FALSE, FALSE,
3063 EL_NUT, -1, MV_BIT_RIGHT
3066 Xnut_force_w, FALSE, FALSE,
3067 EL_NUT, -1, MV_BIT_LEFT
3070 Xspring_force_e, FALSE, FALSE,
3071 EL_SPRING, -1, MV_BIT_RIGHT
3074 Xspring_force_w, FALSE, FALSE,
3075 EL_SPRING, -1, MV_BIT_LEFT
3078 Xemerald_force_e, FALSE, FALSE,
3079 EL_EMERALD, -1, MV_BIT_RIGHT
3082 Xemerald_force_w, FALSE, FALSE,
3083 EL_EMERALD, -1, MV_BIT_LEFT
3086 Xdiamond_force_e, FALSE, FALSE,
3087 EL_DIAMOND, -1, MV_BIT_RIGHT
3090 Xdiamond_force_w, FALSE, FALSE,
3091 EL_DIAMOND, -1, MV_BIT_LEFT
3094 Xbomb_force_e, FALSE, FALSE,
3095 EL_BOMB, -1, MV_BIT_RIGHT
3098 Xbomb_force_w, FALSE, FALSE,
3099 EL_BOMB, -1, MV_BIT_LEFT
3101 #endif /* EM_ENGINE_BAD_ROLL */
3104 Xstone, TRUE, FALSE,
3108 Xstone_pause, FALSE, FALSE,
3112 Xstone_fall, FALSE, FALSE,
3116 Ystone_s, FALSE, FALSE,
3117 EL_ROCK, ACTION_FALLING, -1
3120 Ystone_sB, FALSE, TRUE,
3121 EL_ROCK, ACTION_FALLING, -1
3124 Ystone_e, FALSE, FALSE,
3125 EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT
3128 Ystone_eB, FALSE, TRUE,
3129 EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT
3132 Ystone_w, FALSE, FALSE,
3133 EL_ROCK, ACTION_MOVING, MV_BIT_LEFT
3136 Ystone_wB, FALSE, TRUE,
3137 EL_ROCK, ACTION_MOVING, MV_BIT_LEFT
3144 Xnut_pause, FALSE, FALSE,
3148 Xnut_fall, FALSE, FALSE,
3152 Ynut_s, FALSE, FALSE,
3153 EL_NUT, ACTION_FALLING, -1
3156 Ynut_sB, FALSE, TRUE,
3157 EL_NUT, ACTION_FALLING, -1
3160 Ynut_e, FALSE, FALSE,
3161 EL_NUT, ACTION_MOVING, MV_BIT_RIGHT
3164 Ynut_eB, FALSE, TRUE,
3165 EL_NUT, ACTION_MOVING, MV_BIT_RIGHT
3168 Ynut_w, FALSE, FALSE,
3169 EL_NUT, ACTION_MOVING, MV_BIT_LEFT
3172 Ynut_wB, FALSE, TRUE,
3173 EL_NUT, ACTION_MOVING, MV_BIT_LEFT
3176 Xbug_n, TRUE, FALSE,
3180 Xbug_e, TRUE, FALSE,
3181 EL_BUG_RIGHT, -1, -1
3184 Xbug_s, TRUE, FALSE,
3188 Xbug_w, TRUE, FALSE,
3192 Xbug_gon, FALSE, FALSE,
3196 Xbug_goe, FALSE, FALSE,
3197 EL_BUG_RIGHT, -1, -1
3200 Xbug_gos, FALSE, FALSE,
3204 Xbug_gow, FALSE, FALSE,
3208 Ybug_n, FALSE, FALSE,
3209 EL_BUG, ACTION_MOVING, MV_BIT_UP
3212 Ybug_nB, FALSE, TRUE,
3213 EL_BUG, ACTION_MOVING, MV_BIT_UP
3216 Ybug_e, FALSE, FALSE,
3217 EL_BUG, ACTION_MOVING, MV_BIT_RIGHT
3220 Ybug_eB, FALSE, TRUE,
3221 EL_BUG, ACTION_MOVING, MV_BIT_RIGHT
3224 Ybug_s, FALSE, FALSE,
3225 EL_BUG, ACTION_MOVING, MV_BIT_DOWN
3228 Ybug_sB, FALSE, TRUE,
3229 EL_BUG, ACTION_MOVING, MV_BIT_DOWN
3232 Ybug_w, FALSE, FALSE,
3233 EL_BUG, ACTION_MOVING, MV_BIT_LEFT
3236 Ybug_wB, FALSE, TRUE,
3237 EL_BUG, ACTION_MOVING, MV_BIT_LEFT
3240 Ybug_w_n, FALSE, FALSE,
3241 EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_UP
3244 Ybug_n_e, FALSE, FALSE,
3245 EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3248 Ybug_e_s, FALSE, FALSE,
3249 EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
3252 Ybug_s_w, FALSE, FALSE,
3253 EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3256 Ybug_e_n, FALSE, FALSE,
3257 EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
3260 Ybug_s_e, FALSE, FALSE,
3261 EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3264 Ybug_w_s, FALSE, FALSE,
3265 EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
3268 Ybug_n_w, FALSE, FALSE,
3269 EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3272 Ybug_stone, FALSE, FALSE,
3273 EL_BUG, ACTION_SMASHED_BY_ROCK, -1
3276 Ybug_spring, FALSE, FALSE,
3277 EL_BUG, ACTION_SMASHED_BY_SPRING, -1
3280 Xtank_n, TRUE, FALSE,
3281 EL_SPACESHIP_UP, -1, -1
3284 Xtank_e, TRUE, FALSE,
3285 EL_SPACESHIP_RIGHT, -1, -1
3288 Xtank_s, TRUE, FALSE,
3289 EL_SPACESHIP_DOWN, -1, -1
3292 Xtank_w, TRUE, FALSE,
3293 EL_SPACESHIP_LEFT, -1, -1
3296 Xtank_gon, FALSE, FALSE,
3297 EL_SPACESHIP_UP, -1, -1
3300 Xtank_goe, FALSE, FALSE,
3301 EL_SPACESHIP_RIGHT, -1, -1
3304 Xtank_gos, FALSE, FALSE,
3305 EL_SPACESHIP_DOWN, -1, -1
3308 Xtank_gow, FALSE, FALSE,
3309 EL_SPACESHIP_LEFT, -1, -1
3312 Ytank_n, FALSE, FALSE,
3313 EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP
3316 Ytank_nB, FALSE, TRUE,
3317 EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP
3320 Ytank_e, FALSE, FALSE,
3321 EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT
3324 Ytank_eB, FALSE, TRUE,
3325 EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT
3328 Ytank_s, FALSE, FALSE,
3329 EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN
3332 Ytank_sB, FALSE, TRUE,
3333 EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN
3336 Ytank_w, FALSE, FALSE,
3337 EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT
3340 Ytank_wB, FALSE, TRUE,
3341 EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT
3344 Ytank_w_n, FALSE, FALSE,
3345 EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_UP
3348 Ytank_n_e, FALSE, FALSE,
3349 EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3352 Ytank_e_s, FALSE, FALSE,
3353 EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
3356 Ytank_s_w, FALSE, FALSE,
3357 EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3360 Ytank_e_n, FALSE, FALSE,
3361 EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
3364 Ytank_s_e, FALSE, FALSE,
3365 EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3368 Ytank_w_s, FALSE, FALSE,
3369 EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
3372 Ytank_n_w, FALSE, FALSE,
3373 EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3376 Ytank_stone, FALSE, FALSE,
3377 EL_SPACESHIP, ACTION_SMASHED_BY_ROCK, -1
3380 Ytank_spring, FALSE, FALSE,
3381 EL_SPACESHIP, ACTION_SMASHED_BY_SPRING, -1
3384 Xandroid, TRUE, FALSE,
3385 EL_EMC_ANDROID, ACTION_ACTIVE, -1
3388 Xandroid_1_n, FALSE, FALSE,
3389 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_UP
3392 Xandroid_2_n, FALSE, FALSE,
3393 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_UP
3396 Xandroid_1_e, FALSE, FALSE,
3397 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_RIGHT
3400 Xandroid_2_e, FALSE, FALSE,
3401 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_RIGHT
3404 Xandroid_1_w, FALSE, FALSE,
3405 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_LEFT
3408 Xandroid_2_w, FALSE, FALSE,
3409 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_LEFT
3412 Xandroid_1_s, FALSE, FALSE,
3413 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_DOWN
3416 Xandroid_2_s, FALSE, FALSE,
3417 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_DOWN
3420 Yandroid_n, FALSE, FALSE,
3421 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_UP
3424 Yandroid_nB, FALSE, TRUE,
3425 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_UP
3428 Yandroid_ne, FALSE, FALSE,
3429 EL_EMC_ANDROID, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3432 Yandroid_neB, FALSE, TRUE,
3433 EL_EMC_ANDROID, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3436 Yandroid_e, FALSE, FALSE,
3437 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_RIGHT
3440 Yandroid_eB, FALSE, TRUE,
3441 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_RIGHT
3444 Yandroid_se, FALSE, FALSE,
3445 EL_EMC_ANDROID, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3448 Yandroid_seB, FALSE, TRUE,
3449 EL_EMC_ANDROID, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3452 Yandroid_s, FALSE, FALSE,
3453 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_DOWN
3456 Yandroid_sB, FALSE, TRUE,
3457 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_DOWN
3460 Yandroid_sw, FALSE, FALSE,
3461 EL_EMC_ANDROID, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3464 Yandroid_swB, FALSE, TRUE,
3465 EL_EMC_ANDROID, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3468 Yandroid_w, FALSE, FALSE,
3469 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_LEFT
3472 Yandroid_wB, FALSE, TRUE,
3473 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_LEFT
3476 Yandroid_nw, FALSE, FALSE,
3477 EL_EMC_ANDROID, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3480 Yandroid_nwB, FALSE, TRUE,
3481 EL_EMC_ANDROID, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3484 Xspring, TRUE, FALSE,
3488 Xspring_pause, FALSE, FALSE,
3492 Xspring_e, FALSE, FALSE,
3496 Xspring_w, FALSE, FALSE,
3500 Xspring_fall, FALSE, FALSE,
3504 Yspring_s, FALSE, FALSE,
3505 EL_SPRING, ACTION_FALLING, -1
3508 Yspring_sB, FALSE, TRUE,
3509 EL_SPRING, ACTION_FALLING, -1
3512 Yspring_e, FALSE, FALSE,
3513 EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT
3516 Yspring_eB, FALSE, TRUE,
3517 EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT
3520 Yspring_w, FALSE, FALSE,
3521 EL_SPRING, ACTION_MOVING, MV_BIT_LEFT
3524 Yspring_wB, FALSE, TRUE,
3525 EL_SPRING, ACTION_MOVING, MV_BIT_LEFT
3528 Yspring_kill_e, FALSE, FALSE,
3529 EL_ROBOT, ACTION_SLURPED_BY_SPRING, MV_BIT_RIGHT
3532 Yspring_kill_eB, FALSE, TRUE,
3533 EL_ROBOT, ACTION_SLURPED_BY_SPRING, MV_BIT_RIGHT
3536 Yspring_kill_w, FALSE, FALSE,
3537 EL_ROBOT, ACTION_SLURPED_BY_SPRING, MV_BIT_LEFT
3540 Yspring_kill_wB, FALSE, TRUE,
3541 EL_ROBOT, ACTION_SLURPED_BY_SPRING, MV_BIT_LEFT
3544 Xeater_n, TRUE, FALSE,
3548 Xeater_e, FALSE, FALSE,
3552 Xeater_w, FALSE, FALSE,
3556 Xeater_s, FALSE, FALSE,
3560 Yeater_n, FALSE, FALSE,
3561 EL_YAMYAM, ACTION_MOVING, MV_BIT_UP
3564 Yeater_nB, FALSE, TRUE,
3565 EL_YAMYAM, ACTION_MOVING, MV_BIT_UP
3568 Yeater_e, FALSE, FALSE,
3569 EL_YAMYAM, ACTION_MOVING, MV_BIT_RIGHT
3572 Yeater_eB, FALSE, TRUE,
3573 EL_YAMYAM, ACTION_MOVING, MV_BIT_RIGHT
3576 Yeater_s, FALSE, FALSE,
3577 EL_YAMYAM, ACTION_MOVING, MV_BIT_DOWN
3580 Yeater_sB, FALSE, TRUE,
3581 EL_YAMYAM, ACTION_MOVING, MV_BIT_DOWN
3584 Yeater_w, FALSE, FALSE,
3585 EL_YAMYAM, ACTION_MOVING, MV_BIT_LEFT
3588 Yeater_wB, FALSE, TRUE,
3589 EL_YAMYAM, ACTION_MOVING, MV_BIT_LEFT
3592 Yeater_stone, FALSE, FALSE,
3593 EL_YAMYAM, ACTION_SMASHED_BY_ROCK, -1
3596 Yeater_spring, FALSE, FALSE,
3597 EL_YAMYAM, ACTION_SMASHED_BY_SPRING, -1
3600 Xalien, TRUE, FALSE,
3604 Xalien_pause, FALSE, FALSE,
3608 Yalien_n, FALSE, FALSE,
3609 EL_ROBOT, ACTION_MOVING, MV_BIT_UP
3612 Yalien_nB, FALSE, TRUE,
3613 EL_ROBOT, ACTION_MOVING, MV_BIT_UP
3616 Yalien_e, FALSE, FALSE,
3617 EL_ROBOT, ACTION_MOVING, MV_BIT_RIGHT
3620 Yalien_eB, FALSE, TRUE,
3621 EL_ROBOT, ACTION_MOVING, MV_BIT_RIGHT
3624 Yalien_s, FALSE, FALSE,
3625 EL_ROBOT, ACTION_MOVING, MV_BIT_DOWN
3628 Yalien_sB, FALSE, TRUE,
3629 EL_ROBOT, ACTION_MOVING, MV_BIT_DOWN
3632 Yalien_w, FALSE, FALSE,
3633 EL_ROBOT, ACTION_MOVING, MV_BIT_LEFT
3636 Yalien_wB, FALSE, TRUE,
3637 EL_ROBOT, ACTION_MOVING, MV_BIT_LEFT
3640 Yalien_stone, FALSE, FALSE,
3641 EL_ROBOT, ACTION_SMASHED_BY_ROCK, -1
3644 Yalien_spring, FALSE, FALSE,
3645 EL_ROBOT, ACTION_SMASHED_BY_SPRING, -1
3648 Xemerald, TRUE, FALSE,
3652 Xemerald_pause, FALSE, FALSE,
3656 Xemerald_fall, FALSE, FALSE,
3660 Xemerald_shine, FALSE, FALSE,
3661 EL_EMERALD, ACTION_TWINKLING, -1
3664 Yemerald_s, FALSE, FALSE,
3665 EL_EMERALD, ACTION_FALLING, -1
3668 Yemerald_sB, FALSE, TRUE,
3669 EL_EMERALD, ACTION_FALLING, -1
3672 Yemerald_e, FALSE, FALSE,
3673 EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT
3676 Yemerald_eB, FALSE, TRUE,
3677 EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT
3680 Yemerald_w, FALSE, FALSE,
3681 EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT
3684 Yemerald_wB, FALSE, TRUE,
3685 EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT
3688 Yemerald_eat, FALSE, FALSE,
3689 EL_EMERALD, ACTION_COLLECTING, -1
3692 Yemerald_stone, FALSE, FALSE,
3693 EL_NUT, ACTION_BREAKING, -1
3696 Xdiamond, TRUE, FALSE,
3700 Xdiamond_pause, FALSE, FALSE,
3704 Xdiamond_fall, FALSE, FALSE,
3708 Xdiamond_shine, FALSE, FALSE,
3709 EL_DIAMOND, ACTION_TWINKLING, -1
3712 Ydiamond_s, FALSE, FALSE,
3713 EL_DIAMOND, ACTION_FALLING, -1
3716 Ydiamond_sB, FALSE, TRUE,
3717 EL_DIAMOND, ACTION_FALLING, -1
3720 Ydiamond_e, FALSE, FALSE,
3721 EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT
3724 Ydiamond_eB, FALSE, TRUE,
3725 EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT
3728 Ydiamond_w, FALSE, FALSE,
3729 EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT
3732 Ydiamond_wB, FALSE, TRUE,
3733 EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT
3736 Ydiamond_eat, FALSE, FALSE,
3737 EL_DIAMOND, ACTION_COLLECTING, -1
3740 Ydiamond_stone, FALSE, FALSE,
3741 EL_DIAMOND, ACTION_SMASHED_BY_ROCK, -1
3744 Xdrip_fall, TRUE, FALSE,
3745 EL_AMOEBA_DROP, -1, -1
3748 Xdrip_stretch, FALSE, FALSE,
3749 EL_AMOEBA_DROP, ACTION_FALLING, -1
3752 Xdrip_stretchB, FALSE, TRUE,
3753 EL_AMOEBA_DROP, ACTION_FALLING, -1
3756 Xdrip_eat, FALSE, FALSE,
3757 EL_AMOEBA_DROP, ACTION_GROWING, -1
3760 Ydrip_s1, FALSE, FALSE,
3761 EL_AMOEBA_DROP, ACTION_FALLING, -1
3764 Ydrip_s1B, FALSE, TRUE,
3765 EL_AMOEBA_DROP, ACTION_FALLING, -1
3768 Ydrip_s2, FALSE, FALSE,
3769 EL_AMOEBA_DROP, ACTION_FALLING, -1
3772 Ydrip_s2B, FALSE, TRUE,
3773 EL_AMOEBA_DROP, ACTION_FALLING, -1
3780 Xbomb_pause, FALSE, FALSE,
3784 Xbomb_fall, FALSE, FALSE,
3788 Ybomb_s, FALSE, FALSE,
3789 EL_BOMB, ACTION_FALLING, -1
3792 Ybomb_sB, FALSE, TRUE,
3793 EL_BOMB, ACTION_FALLING, -1
3796 Ybomb_e, FALSE, FALSE,
3797 EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT
3800 Ybomb_eB, FALSE, TRUE,
3801 EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT
3804 Ybomb_w, FALSE, FALSE,
3805 EL_BOMB, ACTION_MOVING, MV_BIT_LEFT
3808 Ybomb_wB, FALSE, TRUE,
3809 EL_BOMB, ACTION_MOVING, MV_BIT_LEFT
3812 Ybomb_eat, FALSE, FALSE,
3813 EL_BOMB, ACTION_SMASHED_BY_ROCK, -1
3816 Xballoon, TRUE, FALSE,
3820 Yballoon_n, FALSE, FALSE,
3821 EL_BALLOON, ACTION_MOVING, MV_BIT_UP
3824 Yballoon_nB, FALSE, TRUE,
3825 EL_BALLOON, ACTION_MOVING, MV_BIT_UP
3828 Yballoon_e, FALSE, FALSE,
3829 EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT
3832 Yballoon_eB, FALSE, TRUE,
3833 EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT
3836 Yballoon_s, FALSE, FALSE,
3837 EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN
3840 Yballoon_sB, FALSE, TRUE,
3841 EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN
3844 Yballoon_w, FALSE, FALSE,
3845 EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT
3848 Yballoon_wB, FALSE, TRUE,
3849 EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT
3852 Xgrass, TRUE, FALSE,
3853 EL_EMC_GRASS, -1, -1
3856 Ygrass_nB, FALSE, FALSE,
3857 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_UP
3860 Ygrass_eB, FALSE, FALSE,
3861 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_RIGHT
3864 Ygrass_sB, FALSE, FALSE,
3865 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_DOWN
3868 Ygrass_wB, FALSE, FALSE,
3869 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_LEFT
3876 Ydirt_nB, FALSE, FALSE,
3877 EL_SAND, ACTION_DIGGING, MV_BIT_UP
3880 Ydirt_eB, FALSE, FALSE,
3881 EL_SAND, ACTION_DIGGING, MV_BIT_RIGHT
3884 Ydirt_sB, FALSE, FALSE,
3885 EL_SAND, ACTION_DIGGING, MV_BIT_DOWN
3888 Ydirt_wB, FALSE, FALSE,
3889 EL_SAND, ACTION_DIGGING, MV_BIT_LEFT
3892 Xacid_ne, TRUE, FALSE,
3893 EL_ACID_POOL_TOPRIGHT, -1, -1
3896 Xacid_se, TRUE, FALSE,
3897 EL_ACID_POOL_BOTTOMRIGHT, -1, -1
3900 Xacid_s, TRUE, FALSE,
3901 EL_ACID_POOL_BOTTOM, -1, -1
3904 Xacid_sw, TRUE, FALSE,
3905 EL_ACID_POOL_BOTTOMLEFT, -1, -1
3908 Xacid_nw, TRUE, FALSE,
3909 EL_ACID_POOL_TOPLEFT, -1, -1
3912 Xacid_1, TRUE, FALSE,
3916 Xacid_2, FALSE, FALSE,
3920 Xacid_3, FALSE, FALSE,
3924 Xacid_4, FALSE, FALSE,
3928 Xacid_5, FALSE, FALSE,
3932 Xacid_6, FALSE, FALSE,
3936 Xacid_7, FALSE, FALSE,
3940 Xacid_8, FALSE, FALSE,
3944 Xball_1, TRUE, FALSE,
3945 EL_EMC_MAGIC_BALL, -1, -1
3948 Xball_1B, FALSE, FALSE,
3949 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
3952 Xball_2, FALSE, FALSE,
3953 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
3956 Xball_2B, FALSE, FALSE,
3957 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
3960 Yball_eat, FALSE, FALSE,
3961 EL_EMC_MAGIC_BALL, ACTION_DROPPING, -1
3964 Ykey_1_eat, FALSE, FALSE,
3965 EL_EM_KEY_1, ACTION_COLLECTING, -1
3968 Ykey_2_eat, FALSE, FALSE,
3969 EL_EM_KEY_2, ACTION_COLLECTING, -1
3972 Ykey_3_eat, FALSE, FALSE,
3973 EL_EM_KEY_3, ACTION_COLLECTING, -1
3976 Ykey_4_eat, FALSE, FALSE,
3977 EL_EM_KEY_4, ACTION_COLLECTING, -1
3980 Ykey_5_eat, FALSE, FALSE,
3981 EL_EM_KEY_5, ACTION_COLLECTING, -1
3984 Ykey_6_eat, FALSE, FALSE,
3985 EL_EM_KEY_6, ACTION_COLLECTING, -1
3988 Ykey_7_eat, FALSE, FALSE,
3989 EL_EM_KEY_7, ACTION_COLLECTING, -1
3992 Ykey_8_eat, FALSE, FALSE,
3993 EL_EM_KEY_8, ACTION_COLLECTING, -1
3996 Ylenses_eat, FALSE, FALSE,
3997 EL_EMC_LENSES, ACTION_COLLECTING, -1
4000 Ymagnify_eat, FALSE, FALSE,
4001 EL_EMC_MAGNIFIER, ACTION_COLLECTING, -1
4004 Ygrass_eat, FALSE, FALSE,
4005 EL_EMC_GRASS, ACTION_SNAPPING, -1
4008 Ydirt_eat, FALSE, FALSE,
4009 EL_SAND, ACTION_SNAPPING, -1
4012 Xgrow_ns, TRUE, FALSE,
4013 EL_EXPANDABLE_WALL_VERTICAL, -1, -1
4016 Ygrow_ns_eat, FALSE, FALSE,
4017 EL_EXPANDABLE_WALL_VERTICAL, ACTION_GROWING, -1
4020 Xgrow_ew, TRUE, FALSE,
4021 EL_EXPANDABLE_WALL_HORIZONTAL, -1, -1
4024 Ygrow_ew_eat, FALSE, FALSE,
4025 EL_EXPANDABLE_WALL_HORIZONTAL, ACTION_GROWING, -1
4028 Xwonderwall, TRUE, FALSE,
4029 EL_MAGIC_WALL, -1, -1
4032 XwonderwallB, FALSE, FALSE,
4033 EL_MAGIC_WALL, ACTION_ACTIVE, -1
4036 Xamoeba_1, TRUE, FALSE,
4037 EL_AMOEBA_DRY, ACTION_OTHER, -1
4040 Xamoeba_2, FALSE, FALSE,
4041 EL_AMOEBA_DRY, ACTION_OTHER, -1
4044 Xamoeba_3, FALSE, FALSE,
4045 EL_AMOEBA_DRY, ACTION_OTHER, -1
4048 Xamoeba_4, FALSE, FALSE,
4049 EL_AMOEBA_DRY, ACTION_OTHER, -1
4052 Xamoeba_5, FALSE, FALSE,
4053 EL_AMOEBA_WET, ACTION_OTHER, -1
4056 Xamoeba_6, FALSE, FALSE,
4057 EL_AMOEBA_WET, ACTION_OTHER, -1
4060 Xamoeba_7, FALSE, FALSE,
4061 EL_AMOEBA_WET, ACTION_OTHER, -1
4064 Xamoeba_8, FALSE, FALSE,
4065 EL_AMOEBA_WET, ACTION_OTHER, -1
4068 Xdoor_1, TRUE, FALSE,
4069 EL_EM_GATE_1, -1, -1
4072 Xdoor_2, TRUE, FALSE,
4073 EL_EM_GATE_2, -1, -1
4076 Xdoor_3, TRUE, FALSE,
4077 EL_EM_GATE_3, -1, -1
4080 Xdoor_4, TRUE, FALSE,
4081 EL_EM_GATE_4, -1, -1
4084 Xdoor_5, TRUE, FALSE,
4085 EL_EM_GATE_5, -1, -1
4088 Xdoor_6, TRUE, FALSE,
4089 EL_EM_GATE_6, -1, -1
4092 Xdoor_7, TRUE, FALSE,
4093 EL_EM_GATE_7, -1, -1
4096 Xdoor_8, TRUE, FALSE,
4097 EL_EM_GATE_8, -1, -1
4100 Xkey_1, TRUE, FALSE,
4104 Xkey_2, TRUE, FALSE,
4108 Xkey_3, TRUE, FALSE,
4112 Xkey_4, TRUE, FALSE,
4116 Xkey_5, TRUE, FALSE,
4120 Xkey_6, TRUE, FALSE,
4124 Xkey_7, TRUE, FALSE,
4128 Xkey_8, TRUE, FALSE,
4132 Xwind_n, TRUE, FALSE,
4133 EL_BALLOON_SWITCH_UP, -1, -1
4136 Xwind_e, TRUE, FALSE,
4137 EL_BALLOON_SWITCH_RIGHT, -1, -1
4140 Xwind_s, TRUE, FALSE,
4141 EL_BALLOON_SWITCH_DOWN, -1, -1
4144 Xwind_w, TRUE, FALSE,
4145 EL_BALLOON_SWITCH_LEFT, -1, -1
4148 Xwind_nesw, TRUE, FALSE,
4149 EL_BALLOON_SWITCH_ANY, -1, -1
4152 Xwind_stop, TRUE, FALSE,
4153 EL_BALLOON_SWITCH_NONE, -1, -1
4157 EL_EXIT_CLOSED, -1, -1
4160 Xexit_1, TRUE, FALSE,
4161 EL_EXIT_OPEN, -1, -1
4164 Xexit_2, FALSE, FALSE,
4165 EL_EXIT_OPEN, -1, -1
4168 Xexit_3, FALSE, FALSE,
4169 EL_EXIT_OPEN, -1, -1
4172 Xdynamite, TRUE, FALSE,
4176 Ydynamite_eat, FALSE, FALSE,
4177 EL_DYNAMITE, ACTION_COLLECTING, -1
4180 Xdynamite_1, TRUE, FALSE,
4181 EL_DYNAMITE_ACTIVE, -1, -1
4184 Xdynamite_2, FALSE, FALSE,
4185 EL_DYNAMITE_ACTIVE, -1, -1
4188 Xdynamite_3, FALSE, FALSE,
4189 EL_DYNAMITE_ACTIVE, -1, -1
4192 Xdynamite_4, FALSE, FALSE,
4193 EL_DYNAMITE_ACTIVE, -1, -1
4196 Xbumper, TRUE, FALSE,
4197 EL_EMC_SPRING_BUMPER, -1, -1
4200 XbumperB, FALSE, FALSE,
4201 EL_EMC_SPRING_BUMPER, ACTION_ACTIVE, -1
4204 Xwheel, TRUE, FALSE,
4205 EL_ROBOT_WHEEL, -1, -1
4208 XwheelB, FALSE, FALSE,
4209 EL_ROBOT_WHEEL, ACTION_ACTIVE, -1
4212 Xswitch, TRUE, FALSE,
4213 EL_EMC_MAGIC_BALL_SWITCH, -1, -1
4216 XswitchB, FALSE, FALSE,
4217 EL_EMC_MAGIC_BALL_SWITCH, ACTION_ACTIVE, -1
4221 EL_QUICKSAND_EMPTY, -1, -1
4224 Xsand_stone, TRUE, FALSE,
4225 EL_QUICKSAND_FULL, -1, -1
4228 Xsand_stonein_1, FALSE, FALSE,
4229 EL_ROCK, ACTION_FILLING, -1
4232 Xsand_stonein_2, FALSE, FALSE,
4233 EL_ROCK, ACTION_FILLING, -1
4236 Xsand_stonein_3, FALSE, FALSE,
4237 EL_ROCK, ACTION_FILLING, -1
4240 Xsand_stonein_4, FALSE, FALSE,
4241 EL_ROCK, ACTION_FILLING, -1
4244 Xsand_stonesand_1, FALSE, FALSE,
4245 EL_QUICKSAND_FULL, -1, -1
4248 Xsand_stonesand_2, FALSE, FALSE,
4249 EL_QUICKSAND_FULL, -1, -1
4252 Xsand_stonesand_3, FALSE, FALSE,
4253 EL_QUICKSAND_FULL, -1, -1
4256 Xsand_stonesand_4, FALSE, FALSE,
4257 EL_QUICKSAND_FULL, -1, -1
4260 Xsand_stoneout_1, FALSE, FALSE,
4261 EL_ROCK, ACTION_EMPTYING, -1
4264 Xsand_stoneout_2, FALSE, FALSE,
4265 EL_ROCK, ACTION_EMPTYING, -1
4268 Xsand_sandstone_1, FALSE, FALSE,
4269 EL_QUICKSAND_FULL, -1, -1
4272 Xsand_sandstone_2, FALSE, FALSE,
4273 EL_QUICKSAND_FULL, -1, -1
4276 Xsand_sandstone_3, FALSE, FALSE,
4277 EL_QUICKSAND_FULL, -1, -1
4280 Xsand_sandstone_4, FALSE, FALSE,
4281 EL_QUICKSAND_FULL, -1, -1
4284 Xplant, TRUE, FALSE,
4285 EL_EMC_PLANT, -1, -1
4288 Yplant, FALSE, FALSE,
4289 EL_EMC_PLANT, -1, -1
4292 Xlenses, TRUE, FALSE,
4293 EL_EMC_LENSES, -1, -1
4296 Xmagnify, TRUE, FALSE,
4297 EL_EMC_MAGNIFIER, -1, -1
4300 Xdripper, TRUE, FALSE,
4301 EL_EMC_DRIPPER, -1, -1
4304 XdripperB, FALSE, FALSE,
4305 EL_EMC_DRIPPER, ACTION_ACTIVE, -1
4308 Xfake_blank, TRUE, FALSE,
4309 EL_INVISIBLE_WALL, -1, -1
4312 Xfake_blankB, FALSE, FALSE,
4313 EL_INVISIBLE_WALL, ACTION_ACTIVE, -1
4316 Xfake_grass, TRUE, FALSE,
4317 EL_EMC_FAKE_GRASS, -1, -1
4320 Xfake_grassB, FALSE, FALSE,
4321 EL_EMC_FAKE_GRASS, ACTION_ACTIVE, -1
4324 Xfake_door_1, TRUE, FALSE,
4325 EL_EM_GATE_1_GRAY, -1, -1
4328 Xfake_door_2, TRUE, FALSE,
4329 EL_EM_GATE_2_GRAY, -1, -1
4332 Xfake_door_3, TRUE, FALSE,
4333 EL_EM_GATE_3_GRAY, -1, -1
4336 Xfake_door_4, TRUE, FALSE,
4337 EL_EM_GATE_4_GRAY, -1, -1
4340 Xfake_door_5, TRUE, FALSE,
4341 EL_EM_GATE_5_GRAY, -1, -1
4344 Xfake_door_6, TRUE, FALSE,
4345 EL_EM_GATE_6_GRAY, -1, -1
4348 Xfake_door_7, TRUE, FALSE,
4349 EL_EM_GATE_7_GRAY, -1, -1
4352 Xfake_door_8, TRUE, FALSE,
4353 EL_EM_GATE_8_GRAY, -1, -1
4356 Xsteel_1, TRUE, FALSE,
4357 EL_STEELWALL, -1, -1
4360 Xsteel_2, TRUE, FALSE,
4361 EL_EMC_STEELWALL_2, -1, -1
4364 Xsteel_3, TRUE, FALSE,
4365 EL_EMC_STEELWALL_3, -1, -1
4368 Xsteel_4, TRUE, FALSE,
4369 EL_EMC_STEELWALL_4, -1, -1
4372 Xwall_1, TRUE, FALSE,
4376 Xwall_2, TRUE, FALSE,
4377 EL_EMC_WALL_14, -1, -1
4380 Xwall_3, TRUE, FALSE,
4381 EL_EMC_WALL_15, -1, -1
4384 Xwall_4, TRUE, FALSE,
4385 EL_EMC_WALL_16, -1, -1
4388 Xround_wall_1, TRUE, FALSE,
4389 EL_WALL_SLIPPERY, -1, -1
4392 Xround_wall_2, TRUE, FALSE,
4393 EL_EMC_WALL_SLIPPERY_2, -1, -1
4396 Xround_wall_3, TRUE, FALSE,
4397 EL_EMC_WALL_SLIPPERY_3, -1, -1
4400 Xround_wall_4, TRUE, FALSE,
4401 EL_EMC_WALL_SLIPPERY_4, -1, -1
4404 Xdecor_1, TRUE, FALSE,
4405 EL_EMC_WALL_8, -1, -1
4408 Xdecor_2, TRUE, FALSE,
4409 EL_EMC_WALL_6, -1, -1
4412 Xdecor_3, TRUE, FALSE,
4413 EL_EMC_WALL_4, -1, -1
4416 Xdecor_4, TRUE, FALSE,
4417 EL_EMC_WALL_7, -1, -1
4420 Xdecor_5, TRUE, FALSE,
4421 EL_EMC_WALL_5, -1, -1
4424 Xdecor_6, TRUE, FALSE,
4425 EL_EMC_WALL_9, -1, -1
4428 Xdecor_7, TRUE, FALSE,
4429 EL_EMC_WALL_10, -1, -1
4432 Xdecor_8, TRUE, FALSE,
4433 EL_EMC_WALL_1, -1, -1
4436 Xdecor_9, TRUE, FALSE,
4437 EL_EMC_WALL_2, -1, -1
4440 Xdecor_10, TRUE, FALSE,
4441 EL_EMC_WALL_3, -1, -1
4444 Xdecor_11, TRUE, FALSE,
4445 EL_EMC_WALL_11, -1, -1
4448 Xdecor_12, TRUE, FALSE,
4449 EL_EMC_WALL_12, -1, -1
4452 Xalpha_0, TRUE, FALSE,
4453 EL_CHAR('0'), -1, -1
4456 Xalpha_1, TRUE, FALSE,
4457 EL_CHAR('1'), -1, -1
4460 Xalpha_2, TRUE, FALSE,
4461 EL_CHAR('2'), -1, -1
4464 Xalpha_3, TRUE, FALSE,
4465 EL_CHAR('3'), -1, -1
4468 Xalpha_4, TRUE, FALSE,
4469 EL_CHAR('4'), -1, -1
4472 Xalpha_5, TRUE, FALSE,
4473 EL_CHAR('5'), -1, -1
4476 Xalpha_6, TRUE, FALSE,
4477 EL_CHAR('6'), -1, -1
4480 Xalpha_7, TRUE, FALSE,
4481 EL_CHAR('7'), -1, -1
4484 Xalpha_8, TRUE, FALSE,
4485 EL_CHAR('8'), -1, -1
4488 Xalpha_9, TRUE, FALSE,
4489 EL_CHAR('9'), -1, -1
4492 Xalpha_excla, TRUE, FALSE,
4493 EL_CHAR('!'), -1, -1
4496 Xalpha_quote, TRUE, FALSE,
4497 EL_CHAR('"'), -1, -1
4500 Xalpha_comma, TRUE, FALSE,
4501 EL_CHAR(','), -1, -1
4504 Xalpha_minus, TRUE, FALSE,
4505 EL_CHAR('-'), -1, -1
4508 Xalpha_perio, TRUE, FALSE,
4509 EL_CHAR('.'), -1, -1
4512 Xalpha_colon, TRUE, FALSE,
4513 EL_CHAR(':'), -1, -1
4516 Xalpha_quest, TRUE, FALSE,
4517 EL_CHAR('?'), -1, -1
4520 Xalpha_a, TRUE, FALSE,
4521 EL_CHAR('A'), -1, -1
4524 Xalpha_b, TRUE, FALSE,
4525 EL_CHAR('B'), -1, -1
4528 Xalpha_c, TRUE, FALSE,
4529 EL_CHAR('C'), -1, -1
4532 Xalpha_d, TRUE, FALSE,
4533 EL_CHAR('D'), -1, -1
4536 Xalpha_e, TRUE, FALSE,
4537 EL_CHAR('E'), -1, -1
4540 Xalpha_f, TRUE, FALSE,
4541 EL_CHAR('F'), -1, -1
4544 Xalpha_g, TRUE, FALSE,
4545 EL_CHAR('G'), -1, -1
4548 Xalpha_h, TRUE, FALSE,
4549 EL_CHAR('H'), -1, -1
4552 Xalpha_i, TRUE, FALSE,
4553 EL_CHAR('I'), -1, -1
4556 Xalpha_j, TRUE, FALSE,
4557 EL_CHAR('J'), -1, -1
4560 Xalpha_k, TRUE, FALSE,
4561 EL_CHAR('K'), -1, -1
4564 Xalpha_l, TRUE, FALSE,
4565 EL_CHAR('L'), -1, -1
4568 Xalpha_m, TRUE, FALSE,
4569 EL_CHAR('M'), -1, -1
4572 Xalpha_n, TRUE, FALSE,
4573 EL_CHAR('N'), -1, -1
4576 Xalpha_o, TRUE, FALSE,
4577 EL_CHAR('O'), -1, -1
4580 Xalpha_p, TRUE, FALSE,
4581 EL_CHAR('P'), -1, -1
4584 Xalpha_q, TRUE, FALSE,
4585 EL_CHAR('Q'), -1, -1
4588 Xalpha_r, TRUE, FALSE,
4589 EL_CHAR('R'), -1, -1
4592 Xalpha_s, TRUE, FALSE,
4593 EL_CHAR('S'), -1, -1
4596 Xalpha_t, TRUE, FALSE,
4597 EL_CHAR('T'), -1, -1
4600 Xalpha_u, TRUE, FALSE,
4601 EL_CHAR('U'), -1, -1
4604 Xalpha_v, TRUE, FALSE,
4605 EL_CHAR('V'), -1, -1
4608 Xalpha_w, TRUE, FALSE,
4609 EL_CHAR('W'), -1, -1
4612 Xalpha_x, TRUE, FALSE,
4613 EL_CHAR('X'), -1, -1
4616 Xalpha_y, TRUE, FALSE,
4617 EL_CHAR('Y'), -1, -1
4620 Xalpha_z, TRUE, FALSE,
4621 EL_CHAR('Z'), -1, -1
4624 Xalpha_arrow_e, TRUE, FALSE,
4625 EL_CHAR('>'), -1, -1
4628 Xalpha_arrow_w, TRUE, FALSE,
4629 EL_CHAR('<'), -1, -1
4632 Xalpha_copyr, TRUE, FALSE,
4633 EL_CHAR('©'), -1, -1
4636 Xalpha_copyr, TRUE, FALSE,
4637 EL_CHAR('©'), -1, -1
4641 Xboom_bug, FALSE, FALSE,
4642 EL_BUG, ACTION_EXPLODING, -1
4645 Xboom_bomb, FALSE, FALSE,
4646 EL_BOMB, ACTION_EXPLODING, -1
4649 Xboom_android, FALSE, FALSE,
4650 EL_EMC_ANDROID, ACTION_OTHER, -1
4653 Xboom_1, FALSE, FALSE,
4654 EL_DEFAULT, ACTION_EXPLODING, -1
4657 Xboom_2, FALSE, FALSE,
4658 EL_DEFAULT, ACTION_EXPLODING, -1
4661 Znormal, FALSE, FALSE,
4665 Zdynamite, FALSE, FALSE,
4669 Zplayer, FALSE, FALSE,
4673 ZBORDER, FALSE, FALSE,
4683 static struct Mapping_EM_to_RND_player
4692 em_player_mapping_list[] =
4696 EL_PLAYER_1, ACTION_MOVING, MV_BIT_UP,
4700 EL_PLAYER_1, ACTION_MOVING, MV_BIT_RIGHT,
4704 EL_PLAYER_1, ACTION_MOVING, MV_BIT_DOWN,
4708 EL_PLAYER_1, ACTION_MOVING, MV_BIT_LEFT,
4712 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_UP,
4716 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_RIGHT,
4720 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_DOWN,
4724 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_LEFT,
4728 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_UP,
4732 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_RIGHT,
4736 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_DOWN,
4740 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_LEFT,
4744 EL_PLAYER_2, ACTION_MOVING, MV_BIT_UP,
4748 EL_PLAYER_2, ACTION_MOVING, MV_BIT_RIGHT,
4752 EL_PLAYER_2, ACTION_MOVING, MV_BIT_DOWN,
4756 EL_PLAYER_2, ACTION_MOVING, MV_BIT_LEFT,
4760 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_UP,
4764 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_RIGHT,
4768 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_DOWN,
4772 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_LEFT,
4776 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_UP,
4780 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_RIGHT,
4784 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_DOWN,
4788 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_LEFT,
4792 EL_PLAYER_1, ACTION_DEFAULT, -1,
4796 EL_PLAYER_2, ACTION_DEFAULT, -1,
4805 int map_element_RND_to_EM(int element_rnd)
4807 static unsigned short mapping_RND_to_EM[NUM_FILE_ELEMENTS];
4808 static boolean mapping_initialized = FALSE;
4810 if (!mapping_initialized)
4814 /* return "Xalpha_quest" for all undefined elements in mapping array */
4815 for (i = 0; i < NUM_FILE_ELEMENTS; i++)
4816 mapping_RND_to_EM[i] = Xalpha_quest;
4818 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
4819 if (em_object_mapping_list[i].is_rnd_to_em_mapping)
4820 mapping_RND_to_EM[em_object_mapping_list[i].element_rnd] =
4821 em_object_mapping_list[i].element_em;
4823 mapping_initialized = TRUE;
4826 if (element_rnd >= 0 && element_rnd < NUM_FILE_ELEMENTS)
4827 return mapping_RND_to_EM[element_rnd];
4829 Error(ERR_WARN, "invalid RND level element %d", element_rnd);
4834 int map_element_EM_to_RND(int element_em)
4836 static unsigned short mapping_EM_to_RND[TILE_MAX];
4837 static boolean mapping_initialized = FALSE;
4839 if (!mapping_initialized)
4843 /* return "EL_UNKNOWN" for all undefined elements in mapping array */
4844 for (i = 0; i < TILE_MAX; i++)
4845 mapping_EM_to_RND[i] = EL_UNKNOWN;
4847 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
4848 mapping_EM_to_RND[em_object_mapping_list[i].element_em] =
4849 em_object_mapping_list[i].element_rnd;
4851 mapping_initialized = TRUE;
4854 if (element_em >= 0 && element_em < TILE_MAX)
4855 return mapping_EM_to_RND[element_em];
4857 Error(ERR_WARN, "invalid EM level element %d", element_em);
4864 int map_element_RND_to_EM(int element_rnd)
4866 static unsigned short mapping_RND_to_EM[NUM_FILE_ELEMENTS];
4867 static boolean mapping_initialized = FALSE;
4874 mapping_RND_to_EM_list[] =
4876 { Xblank, EL_EMPTY },
4877 { Xstone, EL_ROCK },
4879 { Xbug_n, EL_BUG_UP },
4880 { Xbug_e, EL_BUG_RIGHT },
4881 { Xbug_s, EL_BUG_DOWN },
4882 { Xbug_w, EL_BUG_LEFT },
4883 { Xtank_n, EL_SPACESHIP_UP },
4884 { Xtank_e, EL_SPACESHIP_RIGHT },
4885 { Xtank_s, EL_SPACESHIP_DOWN },
4886 { Xtank_w, EL_SPACESHIP_LEFT },
4887 { Xandroid, EL_EMC_ANDROID },
4888 { Xandroid_1_n, EL_EMC_ANDROID_UP },
4889 { Xandroid_1_e, EL_EMC_ANDROID_RIGHT },
4890 { Xandroid_1_w, EL_EMC_ANDROID_LEFT },
4891 { Xandroid_1_s, EL_EMC_ANDROID_DOWN },
4892 { Xspring, EL_SPRING },
4893 { Xeater_n, EL_YAMYAM },
4894 { Xalien, EL_ROBOT },
4895 { Xemerald, EL_EMERALD },
4896 { Xdiamond, EL_DIAMOND },
4897 { Xdrip_fall, EL_AMOEBA_DROP },
4899 { Xballoon, EL_BALLOON },
4900 { Xgrass, EL_EMC_GRASS },
4902 { Xacid_ne, EL_ACID_POOL_TOPRIGHT },
4903 { Xacid_se, EL_ACID_POOL_BOTTOMRIGHT },
4904 { Xacid_s, EL_ACID_POOL_BOTTOM },
4905 { Xacid_sw, EL_ACID_POOL_BOTTOMLEFT },
4906 { Xacid_nw, EL_ACID_POOL_TOPLEFT },
4907 { Xacid_1, EL_ACID },
4908 { Xball_1, EL_EMC_MAGIC_BALL },
4909 { Xgrow_ns, EL_EMC_GROW },
4910 { Xwonderwall, EL_MAGIC_WALL },
4911 { Xamoeba_1, EL_AMOEBA_WET },
4912 { Xdoor_1, EL_EM_GATE_1 },
4913 { Xdoor_2, EL_EM_GATE_2 },
4914 { Xdoor_3, EL_EM_GATE_3 },
4915 { Xdoor_4, EL_EM_GATE_4 },
4916 { Xdoor_5, EL_EMC_GATE_5 },
4917 { Xdoor_6, EL_EMC_GATE_6 },
4918 { Xdoor_7, EL_EMC_GATE_7 },
4919 { Xdoor_8, EL_EMC_GATE_8 },
4920 { Xkey_1, EL_EM_KEY_1 },
4921 { Xkey_2, EL_EM_KEY_2 },
4922 { Xkey_3, EL_EM_KEY_3 },
4923 { Xkey_4, EL_EM_KEY_4 },
4924 { Xkey_5, EL_EMC_KEY_5 },
4925 { Xkey_6, EL_EMC_KEY_6 },
4926 { Xkey_7, EL_EMC_KEY_7 },
4927 { Xkey_8, EL_EMC_KEY_8 },
4928 { Xwind_n, EL_BALLOON_SWITCH_UP },
4929 { Xwind_e, EL_BALLOON_SWITCH_RIGHT },
4930 { Xwind_s, EL_BALLOON_SWITCH_DOWN },
4931 { Xwind_w, EL_BALLOON_SWITCH_LEFT },
4932 { Xwind_nesw, EL_BALLOON_SWITCH_ANY },
4933 { Xwind_stop, EL_BALLOON_SWITCH_NONE },
4934 { Xexit, EL_EXIT_CLOSED },
4935 { Xexit_1, EL_EXIT_OPEN },
4936 { Xdynamite, EL_DYNAMITE },
4937 { Xdynamite_1, EL_DYNAMITE_ACTIVE },
4938 { Xbumper, EL_EMC_BUMPER },
4939 { Xwheel, EL_ROBOT_WHEEL },
4940 { Xswitch, EL_UNKNOWN },
4941 { Xsand, EL_QUICKSAND_EMPTY },
4942 { Xsand_stone, EL_QUICKSAND_FULL },
4943 { Xplant, EL_EMC_PLANT },
4944 { Xlenses, EL_EMC_LENSES },
4945 { Xmagnify, EL_EMC_MAGNIFIER },
4946 { Xdripper, EL_UNKNOWN },
4947 { Xfake_blank, EL_INVISIBLE_WALL },
4948 { Xfake_grass, EL_INVISIBLE_SAND },
4949 { Xfake_door_1, EL_EM_GATE_1_GRAY },
4950 { Xfake_door_2, EL_EM_GATE_2_GRAY },
4951 { Xfake_door_3, EL_EM_GATE_3_GRAY },
4952 { Xfake_door_4, EL_EM_GATE_4_GRAY },
4953 { Xfake_door_5, EL_EMC_GATE_5_GRAY },
4954 { Xfake_door_6, EL_EMC_GATE_6_GRAY },
4955 { Xfake_door_7, EL_EMC_GATE_7_GRAY },
4956 { Xfake_door_8, EL_EMC_GATE_8_GRAY },
4957 { Xsteel_1, EL_STEELWALL },
4958 { Xsteel_2, EL_UNKNOWN },
4959 { Xsteel_3, EL_EMC_STEELWALL_1 },
4960 { Xsteel_4, EL_UNKNOWN },
4961 { Xwall_1, EL_WALL },
4962 { Xwall_2, EL_UNKNOWN },
4963 { Xwall_3, EL_UNKNOWN },
4964 { Xwall_4, EL_UNKNOWN },
4965 { Xround_wall_1, EL_WALL_SLIPPERY },
4966 { Xround_wall_2, EL_UNKNOWN },
4967 { Xround_wall_3, EL_UNKNOWN },
4968 { Xround_wall_4, EL_UNKNOWN },
4969 { Xdecor_1, EL_UNKNOWN },
4970 { Xdecor_2, EL_EMC_WALL_6 },
4971 { Xdecor_3, EL_EMC_WALL_4 },
4972 { Xdecor_4, EL_EMC_WALL_5 },
4973 { Xdecor_5, EL_EMC_WALL_7 },
4974 { Xdecor_6, EL_EMC_WALL_8 },
4975 { Xdecor_7, EL_UNKNOWN },
4976 { Xdecor_8, EL_EMC_WALL_1 },
4977 { Xdecor_9, EL_EMC_WALL_2 },
4978 { Xdecor_10, EL_EMC_WALL_3 },
4979 { Xdecor_11, EL_UNKNOWN },
4980 { Xdecor_12, EL_UNKNOWN },
4981 { Xalpha_0, EL_CHAR('0') },
4982 { Xalpha_1, EL_CHAR('1') },
4983 { Xalpha_2, EL_CHAR('2') },
4984 { Xalpha_3, EL_CHAR('3') },
4985 { Xalpha_4, EL_CHAR('4') },
4986 { Xalpha_5, EL_CHAR('5') },
4987 { Xalpha_6, EL_CHAR('6') },
4988 { Xalpha_7, EL_CHAR('7') },
4989 { Xalpha_8, EL_CHAR('8') },
4990 { Xalpha_9, EL_CHAR('9') },
4991 { Xalpha_excla, EL_CHAR('!') },
4992 { Xalpha_quote, EL_CHAR('"') },
4993 { Xalpha_comma, EL_CHAR(',') },
4994 { Xalpha_minus, EL_CHAR('-') },
4995 { Xalpha_perio, EL_CHAR('.') },
4996 { Xalpha_colon, EL_CHAR(':') },
4997 { Xalpha_quest, EL_CHAR('?') },
4998 { Xalpha_a, EL_CHAR('A') },
4999 { Xalpha_b, EL_CHAR('B') },
5000 { Xalpha_c, EL_CHAR('C') },
5001 { Xalpha_d, EL_CHAR('D') },
5002 { Xalpha_e, EL_CHAR('E') },
5003 { Xalpha_f, EL_CHAR('F') },
5004 { Xalpha_g, EL_CHAR('G') },
5005 { Xalpha_h, EL_CHAR('H') },
5006 { Xalpha_i, EL_CHAR('I') },
5007 { Xalpha_j, EL_CHAR('J') },
5008 { Xalpha_k, EL_CHAR('K') },
5009 { Xalpha_l, EL_CHAR('L') },
5010 { Xalpha_m, EL_CHAR('M') },
5011 { Xalpha_n, EL_CHAR('N') },
5012 { Xalpha_o, EL_CHAR('O') },
5013 { Xalpha_p, EL_CHAR('P') },
5014 { Xalpha_q, EL_CHAR('Q') },
5015 { Xalpha_r, EL_CHAR('R') },
5016 { Xalpha_s, EL_CHAR('S') },
5017 { Xalpha_t, EL_CHAR('T') },
5018 { Xalpha_u, EL_CHAR('U') },
5019 { Xalpha_v, EL_CHAR('V') },
5020 { Xalpha_w, EL_CHAR('W') },
5021 { Xalpha_x, EL_CHAR('X') },
5022 { Xalpha_y, EL_CHAR('Y') },
5023 { Xalpha_z, EL_CHAR('Z') },
5024 { Xalpha_arrow_e, EL_CHAR('>') },
5025 { Xalpha_arrow_w, EL_CHAR('<') },
5026 { Xalpha_copyr, EL_CHAR('©') },
5028 { Zplayer, EL_PLAYER_1 },
5029 { Zplayer, EL_PLAYER_2 },
5030 { Zplayer, EL_PLAYER_3 },
5031 { Zplayer, EL_PLAYER_4 },
5033 { ZBORDER, EL_EMC_LEVEL_BORDER },
5038 if (!mapping_initialized)
5042 /* return "Xalpha_quest" for all undefined elements in mapping array */
5043 for (i = 0; i < NUM_FILE_ELEMENTS; i++)
5044 mapping_RND_to_EM[i] = Xalpha_quest;
5046 for (i = 0; mapping_RND_to_EM_list[i].element_rnd != -1; i++)
5047 mapping_RND_to_EM[mapping_RND_to_EM_list[i].element_rnd] =
5048 mapping_RND_to_EM_list[i].element_em;
5050 mapping_initialized = TRUE;
5053 if (element_rnd >= 0 && element_rnd < NUM_FILE_ELEMENTS)
5054 return mapping_RND_to_EM[element_rnd];
5056 Error(ERR_WARN, "invalid RND level element %d", element_rnd);
5061 int map_element_EM_to_RND(int element_em)
5063 static unsigned short mapping_EM_to_RND[TILE_MAX];
5064 static boolean mapping_initialized = FALSE;
5071 em_object_mapping_list[] =
5073 { Xblank, EL_EMPTY },
5074 { Yacid_splash_eB, EL_EMPTY },
5075 { Yacid_splash_wB, EL_EMPTY },
5077 #ifdef EM_ENGINE_BAD_ROLL
5078 { Xstone_force_e, EL_ROCK },
5079 { Xstone_force_w, EL_ROCK },
5080 { Xnut_force_e, EL_NUT },
5081 { Xnut_force_w, EL_NUT },
5082 { Xspring_force_e, EL_SPRING },
5083 { Xspring_force_w, EL_SPRING },
5084 { Xemerald_force_e, EL_EMERALD },
5085 { Xemerald_force_w, EL_EMERALD },
5086 { Xdiamond_force_e, EL_DIAMOND },
5087 { Xdiamond_force_w, EL_DIAMOND },
5088 { Xbomb_force_e, EL_BOMB },
5089 { Xbomb_force_w, EL_BOMB },
5092 { Xstone, EL_ROCK },
5093 { Xstone_pause, EL_ROCK },
5094 { Xstone_fall, EL_ROCK },
5095 { Ystone_s, EL_ROCK },
5096 { Ystone_sB, EL_ROCK },
5097 { Ystone_e, EL_ROCK },
5098 { Ystone_eB, EL_ROCK },
5099 { Ystone_w, EL_ROCK },
5100 { Ystone_wB, EL_ROCK },
5102 { Xnut_pause, EL_NUT },
5103 { Xnut_fall, EL_NUT },
5105 { Ynut_sB, EL_NUT },
5107 { Ynut_eB, EL_NUT },
5109 { Ynut_wB, EL_NUT },
5110 { Xbug_n, EL_BUG_UP },
5111 { Xbug_e, EL_BUG_RIGHT },
5112 { Xbug_s, EL_BUG_DOWN },
5113 { Xbug_w, EL_BUG_LEFT },
5114 { Xbug_gon, EL_BUG_UP },
5115 { Xbug_goe, EL_BUG_RIGHT },
5116 { Xbug_gos, EL_BUG_DOWN },
5117 { Xbug_gow, EL_BUG_LEFT },
5118 { Ybug_n, EL_BUG_UP },
5119 { Ybug_nB, EL_BUG_UP },
5120 { Ybug_e, EL_BUG_RIGHT },
5121 { Ybug_eB, EL_BUG_RIGHT },
5122 { Ybug_s, EL_BUG_DOWN },
5123 { Ybug_sB, EL_BUG_DOWN },
5124 { Ybug_w, EL_BUG_LEFT },
5125 { Ybug_wB, EL_BUG_LEFT },
5126 { Ybug_w_n, EL_BUG_UP },
5127 { Ybug_n_e, EL_BUG_RIGHT },
5128 { Ybug_e_s, EL_BUG_DOWN },
5129 { Ybug_s_w, EL_BUG_LEFT },
5130 { Ybug_e_n, EL_BUG_UP },
5131 { Ybug_s_e, EL_BUG_RIGHT },
5132 { Ybug_w_s, EL_BUG_DOWN },
5133 { Ybug_n_w, EL_BUG_LEFT },
5134 { Ybug_stone, EL_ROCK },
5135 { Ybug_spring, EL_SPRING },
5136 { Xtank_n, EL_SPACESHIP_UP },
5137 { Xtank_e, EL_SPACESHIP_RIGHT },
5138 { Xtank_s, EL_SPACESHIP_DOWN },
5139 { Xtank_w, EL_SPACESHIP_LEFT },
5140 { Xtank_gon, EL_SPACESHIP_UP },
5141 { Xtank_goe, EL_SPACESHIP_RIGHT },
5142 { Xtank_gos, EL_SPACESHIP_DOWN },
5143 { Xtank_gow, EL_SPACESHIP_LEFT },
5144 { Ytank_n, EL_SPACESHIP_UP },
5145 { Ytank_nB, EL_SPACESHIP_UP },
5146 { Ytank_e, EL_SPACESHIP_RIGHT },
5147 { Ytank_eB, EL_SPACESHIP_RIGHT },
5148 { Ytank_s, EL_SPACESHIP_DOWN },
5149 { Ytank_sB, EL_SPACESHIP_DOWN },
5150 { Ytank_w, EL_SPACESHIP_LEFT },
5151 { Ytank_wB, EL_SPACESHIP_LEFT },
5152 { Ytank_w_n, EL_SPACESHIP_UP },
5153 { Ytank_n_e, EL_SPACESHIP_RIGHT },
5154 { Ytank_e_s, EL_SPACESHIP_DOWN },
5155 { Ytank_s_w, EL_SPACESHIP_LEFT },
5156 { Ytank_e_n, EL_SPACESHIP_UP },
5157 { Ytank_s_e, EL_SPACESHIP_RIGHT },
5158 { Ytank_w_s, EL_SPACESHIP_DOWN },
5159 { Ytank_n_w, EL_SPACESHIP_LEFT },
5160 { Ytank_stone, EL_ROCK },
5161 { Ytank_spring, EL_SPRING },
5162 { Xandroid, EL_EMC_ANDROID },
5163 { Xandroid_1_n, EL_EMC_ANDROID_UP },
5164 { Xandroid_2_n, EL_EMC_ANDROID_UP },
5165 { Xandroid_1_e, EL_EMC_ANDROID_RIGHT },
5166 { Xandroid_2_e, EL_EMC_ANDROID_RIGHT },
5167 { Xandroid_1_w, EL_EMC_ANDROID_LEFT },
5168 { Xandroid_2_w, EL_EMC_ANDROID_LEFT },
5169 { Xandroid_1_s, EL_EMC_ANDROID_DOWN },
5170 { Xandroid_2_s, EL_EMC_ANDROID_DOWN },
5171 { Yandroid_n, EL_EMC_ANDROID_UP },
5172 { Yandroid_nB, EL_EMC_ANDROID_UP },
5173 { Yandroid_ne, EL_EMC_ANDROID_RIGHT_UP },
5174 { Yandroid_neB, EL_EMC_ANDROID_RIGHT_UP },
5175 { Yandroid_e, EL_EMC_ANDROID_RIGHT },
5176 { Yandroid_eB, EL_EMC_ANDROID_RIGHT },
5177 { Yandroid_se, EL_EMC_ANDROID_RIGHT_DOWN },
5178 { Yandroid_seB, EL_EMC_ANDROID_RIGHT_DOWN },
5179 { Yandroid_s, EL_EMC_ANDROID_DOWN },
5180 { Yandroid_sB, EL_EMC_ANDROID_DOWN },
5181 { Yandroid_sw, EL_EMC_ANDROID_LEFT_DOWN },
5182 { Yandroid_swB, EL_EMC_ANDROID_LEFT_DOWN },
5183 { Yandroid_w, EL_EMC_ANDROID_LEFT },
5184 { Yandroid_wB, EL_EMC_ANDROID_LEFT },
5185 { Yandroid_nw, EL_EMC_ANDROID_LEFT_UP },
5186 { Yandroid_nwB, EL_EMC_ANDROID_LEFT_UP },
5187 { Xspring, EL_SPRING },
5188 { Xspring_pause, EL_SPRING },
5189 { Xspring_e, EL_SPRING },
5190 { Xspring_w, EL_SPRING },
5191 { Xspring_fall, EL_SPRING },
5192 { Yspring_s, EL_SPRING },
5193 { Yspring_sB, EL_SPRING },
5194 { Yspring_e, EL_SPRING },
5195 { Yspring_eB, EL_SPRING },
5196 { Yspring_w, EL_SPRING },
5197 { Yspring_wB, EL_SPRING },
5198 { Yspring_kill_e, EL_SPRING },
5199 { Yspring_kill_eB, EL_SPRING },
5200 { Yspring_kill_w, EL_SPRING },
5201 { Yspring_kill_wB, EL_SPRING },
5202 { Xeater_n, EL_YAMYAM },
5203 { Xeater_e, EL_YAMYAM },
5204 { Xeater_w, EL_YAMYAM },
5205 { Xeater_s, EL_YAMYAM },
5206 { Yeater_n, EL_YAMYAM },
5207 { Yeater_nB, EL_YAMYAM },
5208 { Yeater_e, EL_YAMYAM },
5209 { Yeater_eB, EL_YAMYAM },
5210 { Yeater_s, EL_YAMYAM },
5211 { Yeater_sB, EL_YAMYAM },
5212 { Yeater_w, EL_YAMYAM },
5213 { Yeater_wB, EL_YAMYAM },
5214 { Yeater_stone, EL_ROCK },
5215 { Yeater_spring, EL_SPRING },
5216 { Xalien, EL_ROBOT },
5217 { Xalien_pause, EL_ROBOT },
5218 { Yalien_n, EL_ROBOT },
5219 { Yalien_nB, EL_ROBOT },
5220 { Yalien_e, EL_ROBOT },
5221 { Yalien_eB, EL_ROBOT },
5222 { Yalien_s, EL_ROBOT },
5223 { Yalien_sB, EL_ROBOT },
5224 { Yalien_w, EL_ROBOT },
5225 { Yalien_wB, EL_ROBOT },
5226 { Yalien_stone, EL_ROCK },
5227 { Yalien_spring, EL_SPRING },
5228 { Xemerald, EL_EMERALD },
5229 { Xemerald_pause, EL_EMERALD },
5230 { Xemerald_fall, EL_EMERALD },
5231 { Xemerald_shine, EL_EMERALD },
5232 { Yemerald_s, EL_EMERALD },
5233 { Yemerald_sB, EL_EMERALD },
5234 { Yemerald_e, EL_EMERALD },
5235 { Yemerald_eB, EL_EMERALD },
5236 { Yemerald_w, EL_EMERALD },
5237 { Yemerald_wB, EL_EMERALD },
5238 { Yemerald_eat, EL_EMERALD },
5239 { Yemerald_stone, EL_ROCK },
5240 { Xdiamond, EL_DIAMOND },
5241 { Xdiamond_pause, EL_DIAMOND },
5242 { Xdiamond_fall, EL_DIAMOND },
5243 { Xdiamond_shine, EL_DIAMOND },
5244 { Ydiamond_s, EL_DIAMOND },
5245 { Ydiamond_sB, EL_DIAMOND },
5246 { Ydiamond_e, EL_DIAMOND },
5247 { Ydiamond_eB, EL_DIAMOND },
5248 { Ydiamond_w, EL_DIAMOND },
5249 { Ydiamond_wB, EL_DIAMOND },
5250 { Ydiamond_eat, EL_DIAMOND },
5251 { Ydiamond_stone, EL_ROCK },
5252 { Xdrip_fall, EL_AMOEBA_DROP },
5253 { Xdrip_stretch, EL_AMOEBA_DROP },
5254 { Xdrip_stretchB, EL_AMOEBA_DROP },
5255 { Xdrip_eat, EL_AMOEBA_DROP },
5256 { Ydrip_s1, EL_AMOEBA_DROP },
5257 { Ydrip_s1B, EL_AMOEBA_DROP },
5258 { Ydrip_s2, EL_AMOEBA_DROP },
5259 { Ydrip_s2B, EL_AMOEBA_DROP },
5261 { Xbomb_pause, EL_BOMB },
5262 { Xbomb_fall, EL_BOMB },
5263 { Ybomb_s, EL_BOMB },
5264 { Ybomb_sB, EL_BOMB },
5265 { Ybomb_e, EL_BOMB },
5266 { Ybomb_eB, EL_BOMB },
5267 { Ybomb_w, EL_BOMB },
5268 { Ybomb_wB, EL_BOMB },
5269 { Ybomb_eat, EL_BOMB },
5270 { Xballoon, EL_BALLOON },
5271 { Yballoon_n, EL_BALLOON },
5272 { Yballoon_nB, EL_BALLOON },
5273 { Yballoon_e, EL_BALLOON },
5274 { Yballoon_eB, EL_BALLOON },
5275 { Yballoon_s, EL_BALLOON },
5276 { Yballoon_sB, EL_BALLOON },
5277 { Yballoon_w, EL_BALLOON },
5278 { Yballoon_wB, EL_BALLOON },
5279 { Xgrass, EL_SAND },
5280 { Ygrass_nB, EL_SAND },
5281 { Ygrass_eB, EL_SAND },
5282 { Ygrass_sB, EL_SAND },
5283 { Ygrass_wB, EL_SAND },
5285 { Ydirt_nB, EL_SAND },
5286 { Ydirt_eB, EL_SAND },
5287 { Ydirt_sB, EL_SAND },
5288 { Ydirt_wB, EL_SAND },
5289 { Xacid_ne, EL_ACID_POOL_TOPRIGHT },
5290 { Xacid_se, EL_ACID_POOL_BOTTOMRIGHT },
5291 { Xacid_s, EL_ACID_POOL_BOTTOM },
5292 { Xacid_sw, EL_ACID_POOL_BOTTOMLEFT },
5293 { Xacid_nw, EL_ACID_POOL_TOPLEFT },
5294 { Xacid_1, EL_ACID },
5295 { Xacid_2, EL_ACID },
5296 { Xacid_3, EL_ACID },
5297 { Xacid_4, EL_ACID },
5298 { Xacid_5, EL_ACID },
5299 { Xacid_6, EL_ACID },
5300 { Xacid_7, EL_ACID },
5301 { Xacid_8, EL_ACID },
5302 { Xball_1, EL_EMC_MAGIC_BALL },
5303 { Xball_1B, EL_EMC_MAGIC_BALL },
5304 { Xball_2, EL_EMC_MAGIC_BALL },
5305 { Xball_2B, EL_EMC_MAGIC_BALL },
5306 { Yball_eat, EL_EMC_MAGIC_BALL },
5307 { Xgrow_ns, EL_EMC_GROW },
5308 { Ygrow_ns_eat, EL_EMC_GROW },
5309 { Xgrow_ew, EL_EMC_GROW },
5310 { Ygrow_ew_eat, EL_EMC_GROW },
5311 { Xwonderwall, EL_MAGIC_WALL },
5312 { XwonderwallB, EL_MAGIC_WALL },
5313 { Xamoeba_1, EL_AMOEBA_WET },
5314 { Xamoeba_2, EL_AMOEBA_WET },
5315 { Xamoeba_3, EL_AMOEBA_WET },
5316 { Xamoeba_4, EL_AMOEBA_WET },
5317 { Xamoeba_5, EL_AMOEBA_WET },
5318 { Xamoeba_6, EL_AMOEBA_WET },
5319 { Xamoeba_7, EL_AMOEBA_WET },
5320 { Xamoeba_8, EL_AMOEBA_WET },
5321 { Xdoor_1, EL_EM_GATE_1 },
5322 { Xdoor_2, EL_EM_GATE_2 },
5323 { Xdoor_3, EL_EM_GATE_3 },
5324 { Xdoor_4, EL_EM_GATE_4 },
5325 { Xdoor_5, EL_EMC_GATE_5 },
5326 { Xdoor_6, EL_EMC_GATE_6 },
5327 { Xdoor_7, EL_EMC_GATE_7 },
5328 { Xdoor_8, EL_EMC_GATE_8 },
5329 { Xkey_1, EL_EM_KEY_1 },
5330 { Xkey_2, EL_EM_KEY_2 },
5331 { Xkey_3, EL_EM_KEY_3 },
5332 { Xkey_4, EL_EM_KEY_4 },
5333 { Xkey_5, EL_EMC_KEY_5 },
5334 { Xkey_6, EL_EMC_KEY_6 },
5335 { Xkey_7, EL_EMC_KEY_7 },
5336 { Xkey_8, EL_EMC_KEY_8 },
5337 { Xwind_n, EL_BALLOON_SWITCH_UP },
5338 { Xwind_e, EL_BALLOON_SWITCH_RIGHT },
5339 { Xwind_s, EL_BALLOON_SWITCH_DOWN },
5340 { Xwind_w, EL_BALLOON_SWITCH_LEFT },
5341 { Xwind_nesw, EL_BALLOON_SWITCH_ANY },
5342 { Xwind_stop, EL_BALLOON_SWITCH_NONE },
5343 { Xexit, EL_EXIT_CLOSED },
5344 { Xexit_1, EL_EXIT_OPEN },
5345 { Xexit_2, EL_EXIT_OPEN },
5346 { Xexit_3, EL_EXIT_OPEN },
5347 { Xdynamite, EL_DYNAMITE },
5348 { Ydynamite_eat, EL_DYNAMITE },
5349 { Xdynamite_1, EL_DYNAMITE_ACTIVE },
5350 { Xdynamite_2, EL_DYNAMITE_ACTIVE },
5351 { Xdynamite_3, EL_DYNAMITE_ACTIVE },
5352 { Xdynamite_4, EL_DYNAMITE_ACTIVE },
5353 { Xbumper, EL_EMC_BUMPER },
5354 { XbumperB, EL_EMC_BUMPER },
5355 { Xwheel, EL_ROBOT_WHEEL },
5356 { XwheelB, EL_ROBOT_WHEEL },
5357 { Xswitch, EL_UNKNOWN },
5358 { XswitchB, EL_UNKNOWN },
5359 { Xsand, EL_QUICKSAND_EMPTY },
5360 { Xsand_stone, EL_QUICKSAND_FULL },
5361 { Xsand_stonein_1, EL_QUICKSAND_FULL },
5362 { Xsand_stonein_2, EL_QUICKSAND_FULL },
5363 { Xsand_stonein_3, EL_QUICKSAND_FULL },
5364 { Xsand_stonein_4, EL_QUICKSAND_FULL },
5365 { Xsand_stonesand_1, EL_QUICKSAND_FULL },
5366 { Xsand_stonesand_2, EL_QUICKSAND_FULL },
5367 { Xsand_stonesand_3, EL_QUICKSAND_FULL },
5368 { Xsand_stonesand_4, EL_QUICKSAND_FULL },
5369 { Xsand_stoneout_1, EL_QUICKSAND_FULL },
5370 { Xsand_stoneout_2, EL_QUICKSAND_FULL },
5371 { Xsand_sandstone_1, EL_QUICKSAND_FULL },
5372 { Xsand_sandstone_2, EL_QUICKSAND_FULL },
5373 { Xsand_sandstone_3, EL_QUICKSAND_FULL },
5374 { Xsand_sandstone_4, EL_QUICKSAND_FULL },
5375 { Xplant, EL_EMC_PLANT },
5376 { Yplant, EL_EMC_PLANT },
5377 { Xlenses, EL_EMC_LENSES },
5378 { Xmagnify, EL_EMC_MAGNIFIER },
5379 { Xdripper, EL_UNKNOWN },
5380 { XdripperB, EL_UNKNOWN },
5381 { Xfake_blank, EL_INVISIBLE_WALL },
5382 { Xfake_blankB, EL_INVISIBLE_WALL },
5383 { Xfake_grass, EL_INVISIBLE_SAND },
5384 { Xfake_grassB, EL_INVISIBLE_SAND },
5385 { Xfake_door_1, EL_EM_GATE_1_GRAY },
5386 { Xfake_door_2, EL_EM_GATE_2_GRAY },
5387 { Xfake_door_3, EL_EM_GATE_3_GRAY },
5388 { Xfake_door_4, EL_EM_GATE_4_GRAY },
5389 { Xfake_door_5, EL_EMC_GATE_5_GRAY },
5390 { Xfake_door_6, EL_EMC_GATE_6_GRAY },
5391 { Xfake_door_7, EL_EMC_GATE_7_GRAY },
5392 { Xfake_door_8, EL_EMC_GATE_8_GRAY },
5393 { Xsteel_1, EL_STEELWALL },
5394 { Xsteel_2, EL_UNKNOWN },
5395 { Xsteel_3, EL_EMC_STEELWALL_1 },
5396 { Xsteel_4, EL_UNKNOWN },
5397 { Xwall_1, EL_WALL },
5398 { Xwall_2, EL_UNKNOWN },
5399 { Xwall_3, EL_UNKNOWN },
5400 { Xwall_4, EL_UNKNOWN },
5401 { Xround_wall_1, EL_WALL_SLIPPERY },
5402 { Xround_wall_2, EL_UNKNOWN },
5403 { Xround_wall_3, EL_UNKNOWN },
5404 { Xround_wall_4, EL_UNKNOWN },
5405 { Xdecor_1, EL_UNKNOWN },
5406 { Xdecor_2, EL_EMC_WALL_6 },
5407 { Xdecor_3, EL_EMC_WALL_4 },
5408 { Xdecor_4, EL_EMC_WALL_5 },
5409 { Xdecor_5, EL_EMC_WALL_7 },
5410 { Xdecor_6, EL_EMC_WALL_8 },
5411 { Xdecor_7, EL_UNKNOWN },
5412 { Xdecor_8, EL_EMC_WALL_1 },
5413 { Xdecor_9, EL_EMC_WALL_2 },
5414 { Xdecor_10, EL_EMC_WALL_3 },
5415 { Xdecor_11, EL_UNKNOWN },
5416 { Xdecor_12, EL_UNKNOWN },
5417 { Xalpha_0, EL_CHAR('0') },
5418 { Xalpha_1, EL_CHAR('1') },
5419 { Xalpha_2, EL_CHAR('2') },
5420 { Xalpha_3, EL_CHAR('3') },
5421 { Xalpha_4, EL_CHAR('4') },
5422 { Xalpha_5, EL_CHAR('5') },
5423 { Xalpha_6, EL_CHAR('6') },
5424 { Xalpha_7, EL_CHAR('7') },
5425 { Xalpha_8, EL_CHAR('8') },
5426 { Xalpha_9, EL_CHAR('9') },
5427 { Xalpha_excla, EL_CHAR('!') },
5428 { Xalpha_quote, EL_CHAR('"') },
5429 { Xalpha_comma, EL_CHAR(',') },
5430 { Xalpha_minus, EL_CHAR('-') },
5431 { Xalpha_perio, EL_CHAR('.') },
5432 { Xalpha_colon, EL_CHAR(':') },
5433 { Xalpha_quest, EL_CHAR('?') },
5434 { Xalpha_a, EL_CHAR('A') },
5435 { Xalpha_b, EL_CHAR('B') },
5436 { Xalpha_c, EL_CHAR('C') },
5437 { Xalpha_d, EL_CHAR('D') },
5438 { Xalpha_e, EL_CHAR('E') },
5439 { Xalpha_f, EL_CHAR('F') },
5440 { Xalpha_g, EL_CHAR('G') },
5441 { Xalpha_h, EL_CHAR('H') },
5442 { Xalpha_i, EL_CHAR('I') },
5443 { Xalpha_j, EL_CHAR('J') },
5444 { Xalpha_k, EL_CHAR('K') },
5445 { Xalpha_l, EL_CHAR('L') },
5446 { Xalpha_m, EL_CHAR('M') },
5447 { Xalpha_n, EL_CHAR('N') },
5448 { Xalpha_o, EL_CHAR('O') },
5449 { Xalpha_p, EL_CHAR('P') },
5450 { Xalpha_q, EL_CHAR('Q') },
5451 { Xalpha_r, EL_CHAR('R') },
5452 { Xalpha_s, EL_CHAR('S') },
5453 { Xalpha_t, EL_CHAR('T') },
5454 { Xalpha_u, EL_CHAR('U') },
5455 { Xalpha_v, EL_CHAR('V') },
5456 { Xalpha_w, EL_CHAR('W') },
5457 { Xalpha_x, EL_CHAR('X') },
5458 { Xalpha_y, EL_CHAR('Y') },
5459 { Xalpha_z, EL_CHAR('Z') },
5460 { Xalpha_arrow_e, EL_CHAR('>') },
5461 { Xalpha_arrow_w, EL_CHAR('<') },
5462 { Xalpha_copyr, EL_CHAR('©') },
5464 { Zplayer, EL_PLAYER_1 },
5466 { ZBORDER, EL_EMC_LEVEL_BORDER },
5471 if (!mapping_initialized)
5475 /* return "EL_UNKNOWN" for all undefined elements in mapping array */
5476 for (i = 0; i < TILE_MAX; i++)
5477 mapping_EM_to_RND[i] = EL_UNKNOWN;
5479 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
5480 mapping_EM_to_RND[em_object_mapping_list[i].element_em] =
5481 em_object_mapping_list[i].element_rnd;
5483 mapping_initialized = TRUE;
5486 if (element_em >= 0 && element_em < TILE_MAX)
5487 return mapping_EM_to_RND[element_em];
5489 Error(ERR_WARN, "invalid EM level element %d", element_em);
5496 int get_next_element(int element)
5500 case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL;
5501 case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY;
5502 case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL;
5503 case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_ACTIVE;
5504 case EL_BD_MAGIC_WALL_FILLING: return EL_BD_MAGIC_WALL_FULL;
5505 case EL_BD_MAGIC_WALL_EMPTYING: return EL_BD_MAGIC_WALL_ACTIVE;
5506 case EL_AMOEBA_DROPPING: return EL_AMOEBA_WET;
5508 default: return element;
5513 int el_act_dir2img(int element, int action, int direction)
5515 element = GFX_ELEMENT(element);
5517 if (direction == MV_NO_MOVING)
5518 return element_info[element].graphic[action];
5520 direction = MV_DIR_BIT(direction);
5522 return element_info[element].direction_graphic[action][direction];
5525 int el_act_dir2img(int element, int action, int direction)
5527 element = GFX_ELEMENT(element);
5528 direction = MV_DIR_BIT(direction); /* default: MV_NO_MOVING => MV_DOWN */
5530 /* direction_graphic[][] == graphic[] for undefined direction graphics */
5531 return element_info[element].direction_graphic[action][direction];
5536 static int el_act_dir2crm(int element, int action, int direction)
5538 element = GFX_ELEMENT(element);
5540 if (direction == MV_NO_MOVING)
5541 return element_info[element].crumbled[action];
5543 direction = MV_DIR_BIT(direction);
5545 return element_info[element].direction_crumbled[action][direction];
5548 static int el_act_dir2crm(int element, int action, int direction)
5550 element = GFX_ELEMENT(element);
5551 direction = MV_DIR_BIT(direction); /* default: MV_NO_MOVING => MV_DOWN */
5553 /* direction_graphic[][] == graphic[] for undefined direction graphics */
5554 return element_info[element].direction_crumbled[action][direction];
5558 int el_act2img(int element, int action)
5560 element = GFX_ELEMENT(element);
5562 return element_info[element].graphic[action];
5565 int el_act2crm(int element, int action)
5567 element = GFX_ELEMENT(element);
5569 return element_info[element].crumbled[action];
5572 int el_dir2img(int element, int direction)
5574 element = GFX_ELEMENT(element);
5576 return el_act_dir2img(element, ACTION_DEFAULT, direction);
5579 int el2baseimg(int element)
5581 return element_info[element].graphic[ACTION_DEFAULT];
5584 int el2img(int element)
5586 element = GFX_ELEMENT(element);
5588 return element_info[element].graphic[ACTION_DEFAULT];
5591 int el2edimg(int element)
5593 element = GFX_ELEMENT(element);
5595 return element_info[element].special_graphic[GFX_SPECIAL_ARG_EDITOR];
5598 int el2preimg(int element)
5600 element = GFX_ELEMENT(element);
5602 return element_info[element].special_graphic[GFX_SPECIAL_ARG_PREVIEW];
5605 int getGameFrameDelay_EM(int native_em_game_frame_delay)
5607 int game_frame_delay_value;
5609 game_frame_delay_value =
5610 (tape.playing && tape.fast_forward ? FfwdFrameDelay :
5611 GameFrameDelay == GAME_FRAME_DELAY ? native_em_game_frame_delay :
5614 if (tape.playing && tape.warp_forward && !tape.pausing)
5615 game_frame_delay_value = 0;
5617 return game_frame_delay_value;
5620 unsigned int InitRND(long seed)
5622 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
5623 return InitEngineRND_EM(seed);
5625 return InitEngineRND(seed);
5628 #define DEBUG_EM_GFX 0
5630 void InitGraphicInfo_EM(void)
5632 struct Mapping_EM_to_RND_object object_mapping[TILE_MAX];
5633 struct Mapping_EM_to_RND_player player_mapping[2][SPR_MAX];
5637 if (graphic_info_em_object[0][0].bitmap == NULL)
5639 /* EM graphics not yet initialized in em_open_all() */
5645 /* always start with reliable default values */
5646 for (i = 0; i < TILE_MAX; i++)
5648 object_mapping[i].element_rnd = EL_UNKNOWN;
5649 object_mapping[i].is_backside = FALSE;
5650 object_mapping[i].action = ACTION_DEFAULT;
5651 object_mapping[i].direction = MV_NO_MOVING;
5654 /* always start with reliable default values */
5655 for (p = 0; p < 2; p++)
5657 for (i = 0; i < SPR_MAX; i++)
5659 player_mapping[p][i].element_rnd = EL_UNKNOWN;
5660 player_mapping[p][i].action = ACTION_DEFAULT;
5661 player_mapping[p][i].direction = MV_NO_MOVING;
5665 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
5667 int e = em_object_mapping_list[i].element_em;
5669 object_mapping[e].element_rnd = em_object_mapping_list[i].element_rnd;
5670 object_mapping[e].is_backside = em_object_mapping_list[i].is_backside;
5672 if (em_object_mapping_list[i].action != -1)
5673 object_mapping[e].action = em_object_mapping_list[i].action;
5675 if (em_object_mapping_list[i].direction != -1)
5676 object_mapping[e].direction = (1 << em_object_mapping_list[i].direction);
5679 for (i = 0; em_player_mapping_list[i].action_em != -1; i++)
5681 int a = em_player_mapping_list[i].action_em;
5682 int p = em_player_mapping_list[i].player_nr;
5684 player_mapping[p][a].element_rnd = em_player_mapping_list[i].element_rnd;
5686 if (em_player_mapping_list[i].action != -1)
5687 player_mapping[p][a].action = em_player_mapping_list[i].action;
5689 if (em_player_mapping_list[i].direction != -1)
5690 player_mapping[p][a].direction =
5691 (1 << em_player_mapping_list[i].direction);
5694 for (i = 0; i < TILE_MAX; i++)
5696 int element = object_mapping[i].element_rnd;
5697 int action = object_mapping[i].action;
5698 int direction = object_mapping[i].direction;
5699 boolean is_backside = object_mapping[i].is_backside;
5700 boolean action_removing = (action == ACTION_DIGGING ||
5701 action == ACTION_SNAPPING ||
5702 action == ACTION_COLLECTING);
5703 boolean action_exploding = ((action == ACTION_EXPLODING ||
5704 action == ACTION_SMASHED_BY_ROCK ||
5705 action == ACTION_SMASHED_BY_SPRING) &&
5706 element != EL_DIAMOND);
5707 boolean action_active = (action == ACTION_ACTIVE);
5708 boolean action_other = (action == ACTION_OTHER);
5710 for (j = 0; j < 8; j++)
5712 int effective_element = (j > 5 && i == Yacid_splash_eB ? EL_EMPTY :
5713 j > 5 && i == Yacid_splash_wB ? EL_EMPTY :
5715 i == Xdrip_stretch ? element :
5716 i == Xdrip_stretchB ? element :
5717 i == Ydrip_s1 ? element :
5718 i == Ydrip_s1B ? element :
5719 i == Xball_1B ? element :
5720 i == Xball_2 ? element :
5721 i == Xball_2B ? element :
5722 i == Yball_eat ? element :
5723 i == Ykey_1_eat ? element :
5724 i == Ykey_2_eat ? element :
5725 i == Ykey_3_eat ? element :
5726 i == Ykey_4_eat ? element :
5727 i == Ykey_5_eat ? element :
5728 i == Ykey_6_eat ? element :
5729 i == Ykey_7_eat ? element :
5730 i == Ykey_8_eat ? element :
5731 i == Ylenses_eat ? element :
5732 i == Ymagnify_eat ? element :
5733 i == Ygrass_eat ? element :
5734 i == Ydirt_eat ? element :
5735 i == Yspring_kill_e ? EL_SPRING :
5736 i == Yspring_kill_w ? EL_SPRING :
5737 i == Yemerald_stone ? EL_EMERALD :
5738 i == Ydiamond_stone ? EL_ROCK :
5739 i == Xsand_stonein_4 ? EL_EMPTY :
5740 i == Xsand_stoneout_2 ? EL_ROCK :
5741 is_backside ? EL_EMPTY :
5742 action_removing ? EL_EMPTY :
5744 int effective_action = (j < 7 ? action :
5745 i == Xdrip_stretch ? action :
5746 i == Xdrip_stretchB ? action :
5747 i == Ydrip_s1 ? action :
5748 i == Ydrip_s1B ? action :
5749 i == Xball_1B ? action :
5750 i == Xball_2 ? action :
5751 i == Xball_2B ? action :
5752 i == Yball_eat ? action :
5753 i == Ykey_1_eat ? action :
5754 i == Ykey_2_eat ? action :
5755 i == Ykey_3_eat ? action :
5756 i == Ykey_4_eat ? action :
5757 i == Ykey_5_eat ? action :
5758 i == Ykey_6_eat ? action :
5759 i == Ykey_7_eat ? action :
5760 i == Ykey_8_eat ? action :
5761 i == Ylenses_eat ? action :
5762 i == Ymagnify_eat ? action :
5763 i == Ygrass_eat ? action :
5764 i == Ydirt_eat ? action :
5765 i == Xsand_stonein_1 ? action :
5766 i == Xsand_stonein_2 ? action :
5767 i == Xsand_stonein_3 ? action :
5768 i == Xsand_stonein_4 ? action :
5769 i == Xsand_stoneout_1 ? action :
5770 i == Xsand_stoneout_2 ? action :
5771 i == Xboom_android ? ACTION_EXPLODING :
5772 action_exploding ? ACTION_EXPLODING :
5773 action_active ? action :
5774 action_other ? action :
5776 int graphic = (el_act_dir2img(effective_element, effective_action,
5778 int crumbled = (el_act_dir2crm(effective_element, effective_action,
5780 int base_graphic = el_act2img(effective_element, ACTION_DEFAULT);
5781 int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT);
5782 boolean has_crumbled_graphics = (base_crumbled != base_graphic);
5783 struct GraphicInfo *g = &graphic_info[graphic];
5784 struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
5787 /* ensure to get symmetric 3-frame, 2-delay animations as used in EM */
5788 boolean special_animation = (action != ACTION_DEFAULT &&
5789 g->anim_frames == 3 &&
5790 g->anim_delay == 2 &&
5791 g->anim_mode & ANIM_LINEAR);
5792 int sync_frame = (i == Xdrip_stretch ? 7 :
5793 i == Xdrip_stretchB ? 7 :
5794 i == Ydrip_s2 ? j + 8 :
5795 i == Ydrip_s2B ? j + 8 :
5805 i == Xball_2B ? j + 8 :
5806 i == Yball_eat ? j + 1 :
5807 i == Ykey_1_eat ? j + 1 :
5808 i == Ykey_2_eat ? j + 1 :
5809 i == Ykey_3_eat ? j + 1 :
5810 i == Ykey_4_eat ? j + 1 :
5811 i == Ykey_5_eat ? j + 1 :
5812 i == Ykey_6_eat ? j + 1 :
5813 i == Ykey_7_eat ? j + 1 :
5814 i == Ykey_8_eat ? j + 1 :
5815 i == Ylenses_eat ? j + 1 :
5816 i == Ymagnify_eat ? j + 1 :
5817 i == Ygrass_eat ? j + 1 :
5818 i == Ydirt_eat ? j + 1 :
5819 i == Xamoeba_1 ? 0 :
5820 i == Xamoeba_2 ? 1 :
5821 i == Xamoeba_3 ? 2 :
5822 i == Xamoeba_4 ? 3 :
5823 i == Xamoeba_5 ? 0 :
5824 i == Xamoeba_6 ? 1 :
5825 i == Xamoeba_7 ? 2 :
5826 i == Xamoeba_8 ? 3 :
5827 i == Xexit_2 ? j + 8 :
5828 i == Xexit_3 ? j + 16 :
5829 i == Xdynamite_1 ? 0 :
5830 i == Xdynamite_2 ? 20 :
5831 i == Xdynamite_3 ? 40 :
5832 i == Xdynamite_4 ? 60 :
5833 i == Xsand_stonein_1 ? j + 1 :
5834 i == Xsand_stonein_2 ? j + 9 :
5835 i == Xsand_stonein_3 ? j + 17 :
5836 i == Xsand_stonein_4 ? j + 25 :
5837 i == Xsand_stoneout_1 && j == 0 ? 0 :
5838 i == Xsand_stoneout_1 && j == 1 ? 0 :
5839 i == Xsand_stoneout_1 && j == 2 ? 1 :
5840 i == Xsand_stoneout_1 && j == 3 ? 2 :
5841 i == Xsand_stoneout_1 && j == 4 ? 2 :
5842 i == Xsand_stoneout_1 && j == 5 ? 3 :
5843 i == Xsand_stoneout_1 && j == 6 ? 4 :
5844 i == Xsand_stoneout_1 && j == 7 ? 4 :
5845 i == Xsand_stoneout_2 && j == 0 ? 5 :
5846 i == Xsand_stoneout_2 && j == 1 ? 6 :
5847 i == Xsand_stoneout_2 && j == 2 ? 7 :
5848 i == Xsand_stoneout_2 && j == 3 ? 8 :
5849 i == Xsand_stoneout_2 && j == 4 ? 9 :
5850 i == Xsand_stoneout_2 && j == 5 ? 11 :
5851 i == Xsand_stoneout_2 && j == 6 ? 13 :
5852 i == Xsand_stoneout_2 && j == 7 ? 15 :
5853 i == Xboom_bug && j == 1 ? 2 :
5854 i == Xboom_bug && j == 2 ? 2 :
5855 i == Xboom_bug && j == 3 ? 4 :
5856 i == Xboom_bug && j == 4 ? 4 :
5857 i == Xboom_bug && j == 5 ? 2 :
5858 i == Xboom_bug && j == 6 ? 2 :
5859 i == Xboom_bug && j == 7 ? 0 :
5860 i == Xboom_bomb && j == 1 ? 2 :
5861 i == Xboom_bomb && j == 2 ? 2 :
5862 i == Xboom_bomb && j == 3 ? 4 :
5863 i == Xboom_bomb && j == 4 ? 4 :
5864 i == Xboom_bomb && j == 5 ? 2 :
5865 i == Xboom_bomb && j == 6 ? 2 :
5866 i == Xboom_bomb && j == 7 ? 0 :
5867 i == Xboom_android && j == 7 ? 6 :
5868 i == Xboom_1 && j == 1 ? 2 :
5869 i == Xboom_1 && j == 2 ? 2 :
5870 i == Xboom_1 && j == 3 ? 4 :
5871 i == Xboom_1 && j == 4 ? 4 :
5872 i == Xboom_1 && j == 5 ? 6 :
5873 i == Xboom_1 && j == 6 ? 6 :
5874 i == Xboom_1 && j == 7 ? 8 :
5875 i == Xboom_2 && j == 0 ? 8 :
5876 i == Xboom_2 && j == 1 ? 8 :
5877 i == Xboom_2 && j == 2 ? 10 :
5878 i == Xboom_2 && j == 3 ? 10 :
5879 i == Xboom_2 && j == 4 ? 10 :
5880 i == Xboom_2 && j == 5 ? 12 :
5881 i == Xboom_2 && j == 6 ? 12 :
5882 i == Xboom_2 && j == 7 ? 12 :
5883 special_animation && j == 4 ? 3 :
5884 effective_action != action ? 0 :
5888 Bitmap *debug_bitmap = g_em->bitmap;
5889 int debug_src_x = g_em->src_x;
5890 int debug_src_y = g_em->src_y;
5893 int frame = getAnimationFrame(g->anim_frames,
5896 g->anim_start_frame,
5899 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y,
5900 g->double_movement && is_backside);
5903 g_em->bitmap = src_bitmap;
5904 g_em->src_x = src_x;
5905 g_em->src_y = src_y;
5906 g_em->src_offset_x = 0;
5907 g_em->src_offset_y = 0;
5908 g_em->dst_offset_x = 0;
5909 g_em->dst_offset_y = 0;
5910 g_em->width = TILEX;
5911 g_em->height = TILEY;
5913 g_em->has_crumbled_graphics = FALSE;
5914 g_em->crumbled_bitmap = NULL;
5915 g_em->crumbled_src_x = 0;
5916 g_em->crumbled_src_y = 0;
5917 g_em->crumbled_border_size = 0;
5921 if (effective_element == EL_EMC_GRASS &&
5922 effective_action == ACTION_DIGGING)
5923 printf("::: %d\n", crumbled);
5927 if (has_crumbled_graphics && crumbled == IMG_EMPTY_SPACE)
5928 printf("::: empty crumbled: %d [%s], %d, %d\n",
5929 effective_element, element_info[effective_element].token_name,
5930 effective_action, direction);
5933 /* if element can be crumbled, but certain action graphics are just empty
5934 space (like snapping sand with the original R'n'D graphics), do not
5935 treat these empty space graphics as crumbled graphics in EMC engine */
5936 if (has_crumbled_graphics && crumbled != IMG_EMPTY_SPACE)
5938 getGraphicSource(crumbled, frame, &src_bitmap, &src_x, &src_y);
5940 g_em->has_crumbled_graphics = TRUE;
5941 g_em->crumbled_bitmap = src_bitmap;
5942 g_em->crumbled_src_x = src_x;
5943 g_em->crumbled_src_y = src_y;
5944 g_em->crumbled_border_size = graphic_info[crumbled].border_size;
5948 if (!g->double_movement && (effective_action == ACTION_FALLING ||
5949 effective_action == ACTION_MOVING ||
5950 effective_action == ACTION_PUSHING))
5953 (effective_action == ACTION_FALLING ? MV_DOWN : direction);
5954 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? 1 : 0);
5955 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? 1 : 0);
5956 int cx = ABS(dx) * TILEX / 8;
5957 int cy = ABS(dy) * TILEY / 8;
5959 if (is_backside) /* tile where movement starts */
5961 if (dx < 0 || dy < 0)
5963 g_em->src_offset_x = cx * (j + 1);
5964 g_em->src_offset_y = cy * (j + 1);
5968 g_em->dst_offset_x = cx * (j + 1);
5969 g_em->dst_offset_y = cy * (j + 1);
5972 g_em->width = TILEX - cx * (j + 1);
5973 g_em->height = TILEY - cy * (j + 1);
5975 else /* tile where movement ends */
5977 if (dx < 0 || dy < 0)
5979 g_em->dst_offset_x = cx * (7 - j);
5980 g_em->dst_offset_y = cy * (7 - j);
5984 g_em->src_offset_x = cx * (7 - j);
5985 g_em->src_offset_y = cy * (7 - j);
5988 g_em->width = TILEX - cx * (7 - j);
5989 g_em->height = TILEY - cy * (7 - j);
5994 /* create unique graphic identifier to decide if tile must be redrawn */
5995 /* bit 31 - 16 (16 bit): EM style element
5996 bit 15 - 12 ( 4 bit): EM style frame
5997 bit 11 - 6 ( 6 bit): graphic width
5998 bit 5 - 0 ( 6 bit): graphic height */
5999 g_em->unique_identifier =
6000 (i << 16) | (j << 12) | (g_em->width << 6) | g_em->height;
6003 if (g_em->bitmap != debug_bitmap ||
6004 g_em->src_x != debug_src_x ||
6005 g_em->src_y != debug_src_y ||
6006 g_em->src_offset_x != 0 ||
6007 g_em->src_offset_y != 0 ||
6008 g_em->dst_offset_x != 0 ||
6009 g_em->dst_offset_y != 0 ||
6010 g_em->width != TILEX ||
6011 g_em->height != TILEY)
6013 static int last_i = -1;
6021 printf("::: EMC GFX ERROR for element %d -> %d ('%s', '%s', %d)",
6022 i, element, element_info[element].token_name,
6023 element_action_info[effective_action].suffix, direction);
6025 if (element != effective_element)
6026 printf(" [%d ('%s')]",
6028 element_info[effective_element].token_name);
6032 if (g_em->bitmap != debug_bitmap)
6033 printf(" %d (%d): different bitmap! (0x%08x != 0x%08x)\n",
6034 j, is_backside, (int)(g_em->bitmap), (int)(debug_bitmap));
6036 if (g_em->src_x != debug_src_x ||
6037 g_em->src_y != debug_src_y)
6038 printf(" frame %d (%c): %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
6039 j, (is_backside ? 'B' : 'F'),
6040 g_em->src_x, g_em->src_y,
6041 g_em->src_x / 32, g_em->src_y / 32,
6042 debug_src_x, debug_src_y,
6043 debug_src_x / 32, debug_src_y / 32);
6045 if (g_em->src_offset_x != 0 ||
6046 g_em->src_offset_y != 0 ||
6047 g_em->dst_offset_x != 0 ||
6048 g_em->dst_offset_y != 0)
6049 printf(" %d (%d): offsets %d,%d and %d,%d should be all 0\n",
6051 g_em->src_offset_x, g_em->src_offset_y,
6052 g_em->dst_offset_x, g_em->dst_offset_y);
6054 if (g_em->width != TILEX ||
6055 g_em->height != TILEY)
6056 printf(" %d (%d): size %d,%d should be %d,%d\n",
6058 g_em->width, g_em->height, TILEX, TILEY);
6065 for (p = 0; p < 2; p++)
6067 for (i = 0; i < SPR_MAX; i++)
6069 int element = player_mapping[p][i].element_rnd;
6070 int action = player_mapping[p][i].action;
6071 int direction = player_mapping[p][i].direction;
6073 for (j = 0; j < 8; j++)
6075 int effective_element = element;
6076 int effective_action = action;
6077 int graphic = (direction == MV_NO_MOVING ?
6078 el_act2img(effective_element, effective_action) :
6079 el_act_dir2img(effective_element, effective_action,
6081 struct GraphicInfo *g = &graphic_info[graphic];
6082 struct GraphicInfo_EM *g_em = &graphic_info_em_player[p][i][7 - j];
6088 Bitmap *debug_bitmap = g_em->bitmap;
6089 int debug_src_x = g_em->src_x;
6090 int debug_src_y = g_em->src_y;
6093 int frame = getAnimationFrame(g->anim_frames,
6096 g->anim_start_frame,
6099 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x,&src_y, FALSE);
6102 g_em->bitmap = src_bitmap;
6103 g_em->src_x = src_x;
6104 g_em->src_y = src_y;
6105 g_em->src_offset_x = 0;
6106 g_em->src_offset_y = 0;
6107 g_em->dst_offset_x = 0;
6108 g_em->dst_offset_y = 0;
6109 g_em->width = TILEX;
6110 g_em->height = TILEY;
6114 if (g_em->bitmap != debug_bitmap ||
6115 g_em->src_x != debug_src_x ||
6116 g_em->src_y != debug_src_y)
6118 static int last_i = -1;
6126 printf("::: EMC GFX ERROR for p/a %d/%d -> %d ('%s', '%s', %d)",
6127 p, i, element, element_info[element].token_name,
6128 element_action_info[effective_action].suffix, direction);
6130 if (element != effective_element)
6131 printf(" [%d ('%s')]",
6133 element_info[effective_element].token_name);
6137 if (g_em->bitmap != debug_bitmap)
6138 printf(" %d: different bitmap! (0x%08x != 0x%08x)\n",
6139 j, (int)(g_em->bitmap), (int)(debug_bitmap));
6141 if (g_em->src_x != debug_src_x ||
6142 g_em->src_y != debug_src_y)
6143 printf(" frame %d: %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
6145 g_em->src_x, g_em->src_y,
6146 g_em->src_x / 32, g_em->src_y / 32,
6147 debug_src_x, debug_src_y,
6148 debug_src_x / 32, debug_src_y / 32);