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 && !game.envelope_active)
132 width = gfx.sxsize + 2 * TILEX;
133 height = gfx.sysize + 2 * TILEY;
136 if (force_redraw || setup.direct_draw)
139 int x1 = (x - SX) / TILEX, y1 = (y - SY) / TILEY;
140 int x2 = (x - SX + width) / TILEX, y2 = (y - SY + height) / TILEY;
142 if (setup.direct_draw)
143 SetDrawtoField(DRAW_BACKBUFFER);
145 for (xx = BX1; xx <= BX2; xx++)
146 for (yy = BY1; yy <= BY2; yy++)
147 if (xx >= x1 && xx <= x2 && yy >= y1 && yy <= y2)
148 DrawScreenField(xx, yy);
151 if (setup.direct_draw)
152 SetDrawtoField(DRAW_DIRECT);
155 if (setup.soft_scrolling)
157 int fx = FX, fy = FY;
159 fx += (ScreenMovDir & (MV_LEFT|MV_RIGHT) ? ScreenGfxPos : 0);
160 fy += (ScreenMovDir & (MV_UP|MV_DOWN) ? ScreenGfxPos : 0);
162 BlitBitmap(fieldbuffer, backbuffer, fx,fy, SXSIZE,SYSIZE, SX,SY);
166 BlitBitmap(drawto, window, x, y, width, height, x, y);
172 DrawBuffer *buffer = (drawto_field == window ? backbuffer : drawto_field);
174 if (setup.direct_draw && game_status == GAME_MODE_PLAYING)
175 redraw_mask &= ~REDRAW_MAIN;
177 if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD)
178 redraw_mask |= REDRAW_FIELD;
180 if (redraw_mask & REDRAW_FIELD)
181 redraw_mask &= ~REDRAW_TILES;
183 if (redraw_mask == REDRAW_NONE)
186 if (global.fps_slowdown && game_status == GAME_MODE_PLAYING)
188 static boolean last_frame_skipped = FALSE;
189 boolean skip_even_when_not_scrolling = TRUE;
190 boolean just_scrolling = (ScreenMovDir != 0);
191 boolean verbose = FALSE;
193 if (global.fps_slowdown_factor > 1 &&
194 (FrameCounter % global.fps_slowdown_factor) &&
195 (just_scrolling || skip_even_when_not_scrolling))
197 redraw_mask &= ~REDRAW_MAIN;
199 last_frame_skipped = TRUE;
202 printf("FRAME SKIPPED\n");
206 if (last_frame_skipped)
207 redraw_mask |= REDRAW_FIELD;
209 last_frame_skipped = FALSE;
212 printf("frame not skipped\n");
216 /* synchronize X11 graphics at this point; if we would synchronize the
217 display immediately after the buffer switching (after the XFlush),
218 this could mean that we have to wait for the graphics to complete,
219 although we could go on doing calculations for the next frame */
223 if (redraw_mask & REDRAW_ALL)
225 BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
229 if (redraw_mask & REDRAW_FIELD)
231 if (game_status != GAME_MODE_PLAYING ||
232 redraw_mask & REDRAW_FROM_BACKBUFFER)
234 BlitBitmap(backbuffer, window,
235 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE, REAL_SX, REAL_SY);
239 int fx = FX, fy = FY;
241 if (setup.soft_scrolling)
243 fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
244 fy += (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
247 if (setup.soft_scrolling ||
248 ABS(ScreenMovPos) + ScrollStepSize == TILEX ||
249 ABS(ScreenMovPos) == ScrollStepSize ||
250 redraw_tiles > REDRAWTILES_THRESHOLD)
252 BlitBitmap(buffer, window, fx, fy, SXSIZE, SYSIZE, SX, SY);
256 printf("redrawing all (ScreenGfxPos == %d) because %s\n",
258 (setup.soft_scrolling ?
259 "setup.soft_scrolling" :
260 ABS(ScreenGfxPos) + ScrollStepSize == TILEX ?
261 "ABS(ScreenGfxPos) + ScrollStepSize == TILEX" :
262 ABS(ScreenGfxPos) == ScrollStepSize ?
263 "ABS(ScreenGfxPos) == ScrollStepSize" :
264 "redraw_tiles > REDRAWTILES_THRESHOLD"));
270 redraw_mask &= ~REDRAW_MAIN;
273 if (redraw_mask & REDRAW_DOORS)
275 if (redraw_mask & REDRAW_DOOR_1)
276 BlitBitmap(backbuffer, window, DX, DY, DXSIZE, DYSIZE, DX, DY);
278 if (redraw_mask & REDRAW_DOOR_2)
281 if ((redraw_mask & REDRAW_DOOR_2) == REDRAW_DOOR_2)
283 BlitBitmap(backbuffer, window, VX, VY, VXSIZE, VYSIZE, VX, VY);
287 if (redraw_mask & REDRAW_VIDEO_1)
288 BlitBitmap(backbuffer, window,
289 VX + VIDEO_DISPLAY1_XPOS, VY + VIDEO_DISPLAY1_YPOS,
290 VIDEO_DISPLAY_XSIZE, VIDEO_DISPLAY_YSIZE,
291 VX + VIDEO_DISPLAY1_XPOS, VY + VIDEO_DISPLAY1_YPOS);
292 if (redraw_mask & REDRAW_VIDEO_2)
293 BlitBitmap(backbuffer, window,
294 VX + VIDEO_DISPLAY2_XPOS, VY + VIDEO_DISPLAY2_YPOS,
295 VIDEO_DISPLAY_XSIZE, VIDEO_DISPLAY_YSIZE,
296 VX + VIDEO_DISPLAY2_XPOS, VY + VIDEO_DISPLAY2_YPOS);
297 if (redraw_mask & REDRAW_VIDEO_3)
298 BlitBitmap(backbuffer, window,
299 VX + VIDEO_CONTROL_XPOS, VY + VIDEO_CONTROL_YPOS,
300 VIDEO_CONTROL_XSIZE, VIDEO_CONTROL_YSIZE,
301 VX + VIDEO_CONTROL_XPOS, VY + VIDEO_CONTROL_YPOS);
306 if (redraw_mask & REDRAW_DOOR_3)
307 BlitBitmap(backbuffer, window, EX, EY, EXSIZE, EYSIZE, EX, EY);
309 redraw_mask &= ~REDRAW_DOORS;
312 if (redraw_mask & REDRAW_MICROLEVEL)
314 BlitBitmap(backbuffer, window, SX, SY + 10 * TILEY, SXSIZE, 7 * TILEY,
315 SX, SY + 10 * TILEY);
317 redraw_mask &= ~REDRAW_MICROLEVEL;
320 if (redraw_mask & REDRAW_TILES)
322 for (x = 0; x < SCR_FIELDX; x++)
323 for (y = 0 ; y < SCR_FIELDY; y++)
324 if (redraw[redraw_x1 + x][redraw_y1 + y])
325 BlitBitmap(buffer, window,
326 FX + x * TILEX, FY + y * TILEY, TILEX, TILEY,
327 SX + x * TILEX, SY + y * TILEY);
330 if (redraw_mask & REDRAW_FPS) /* display frames per second */
335 sprintf(info1, " (only every %d. frame)", global.fps_slowdown_factor);
336 if (!global.fps_slowdown)
339 sprintf(text, "%.1f fps%s", global.frames_per_second, info1);
340 DrawTextExt(window, SX, SY, text, FONT_TEXT_2, BLIT_OPAQUE);
345 for (x = 0; x < MAX_BUF_XSIZE; x++)
346 for (y = 0; y < MAX_BUF_YSIZE; y++)
349 redraw_mask = REDRAW_NONE;
355 long fading_delay = 300;
357 if (setup.fading && (redraw_mask & REDRAW_FIELD))
364 ClearRectangle(window, REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
367 for (i = 0; i < 2 * FULL_SYSIZE; i++)
369 for (y = 0; y < FULL_SYSIZE; y++)
371 BlitBitmap(backbuffer, window,
372 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
380 for (i = 1; i < FULL_SYSIZE; i+=2)
381 BlitBitmap(backbuffer, window,
382 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
388 SetClipOrigin(clip_gc[PIX_FADEMASK], 0, 0);
389 BlitBitmapMasked(backbuffer, window,
390 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
395 SetClipOrigin(clip_gc[PIX_FADEMASK], -1, -1);
396 BlitBitmapMasked(backbuffer, window,
397 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
402 SetClipOrigin(clip_gc[PIX_FADEMASK], 0, -1);
403 BlitBitmapMasked(backbuffer, window,
404 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
409 SetClipOrigin(clip_gc[PIX_FADEMASK], -1, 0);
410 BlitBitmapMasked(backbuffer, window,
411 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
416 redraw_mask &= ~REDRAW_MAIN;
423 void SetMainBackgroundImage(int graphic)
425 SetMainBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
426 graphic_info[graphic].bitmap ?
427 graphic_info[graphic].bitmap :
428 graphic_info[IMG_BACKGROUND].bitmap);
431 void SetDoorBackgroundImage(int graphic)
433 SetDoorBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
434 graphic_info[graphic].bitmap ?
435 graphic_info[graphic].bitmap :
436 graphic_info[IMG_BACKGROUND].bitmap);
439 void DrawBackground(int dst_x, int dst_y, int width, int height)
441 ClearRectangleOnBackground(backbuffer, dst_x, dst_y, width, height);
443 redraw_mask |= REDRAW_FIELD;
448 DrawBackground(REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
450 if (setup.soft_scrolling && game_status == GAME_MODE_PLAYING)
452 ClearRectangle(fieldbuffer, 0, 0, FXSIZE, FYSIZE);
453 SetDrawtoField(DRAW_BUFFERED);
456 SetDrawtoField(DRAW_BACKBUFFER);
458 if (setup.direct_draw && game_status == GAME_MODE_PLAYING)
460 ClearRectangle(window, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
461 SetDrawtoField(DRAW_DIRECT);
465 void MarkTileDirty(int x, int y)
467 int xx = redraw_x1 + x;
468 int yy = redraw_y1 + y;
473 redraw[xx][yy] = TRUE;
474 redraw_mask |= REDRAW_TILES;
477 void SetBorderElement()
481 BorderElement = EL_EMPTY;
483 for (y = 0; y < lev_fieldy && BorderElement == EL_EMPTY; y++)
485 for (x = 0; x < lev_fieldx; x++)
487 if (!IS_INDESTRUCTIBLE(Feld[x][y]))
488 BorderElement = EL_STEELWALL;
490 if (y != 0 && y != lev_fieldy - 1 && x != lev_fieldx - 1)
496 void SetRandomAnimationValue(int x, int y)
498 gfx.anim_random_frame = GfxRandom[x][y];
501 inline int getGraphicAnimationFrame(int graphic, int sync_frame)
503 /* animation synchronized with global frame counter, not move position */
504 if (graphic_info[graphic].anim_global_sync || sync_frame < 0)
505 sync_frame = FrameCounter;
507 return getAnimationFrame(graphic_info[graphic].anim_frames,
508 graphic_info[graphic].anim_delay,
509 graphic_info[graphic].anim_mode,
510 graphic_info[graphic].anim_start_frame,
514 inline void getGraphicSourceExt(int graphic, int frame, Bitmap **bitmap,
515 int *x, int *y, boolean get_backside)
517 struct GraphicInfo *g = &graphic_info[graphic];
518 int src_x = g->src_x + (get_backside ? g->offset2_x : 0);
519 int src_y = g->src_y + (get_backside ? g->offset2_y : 0);
523 if (g->offset_y == 0) /* frames are ordered horizontally */
525 int max_width = g->anim_frames_per_line * g->width;
527 int pos = (src_y / g->height) * max_width + src_x + frame * g->offset_x;
529 *x = pos % max_width;
530 *y = src_y % g->height + pos / max_width * g->height;
532 *x = (src_x + frame * g->offset_x) % max_width;
533 *y = src_y + (src_x + frame * g->offset_x) / max_width * g->height;
536 else if (g->offset_x == 0) /* frames are ordered vertically */
538 int max_height = g->anim_frames_per_line * g->height;
540 int pos = (src_x / g->width) * max_height + src_y + frame * g->offset_y;
542 *x = src_x % g->width + pos / max_height * g->width;
543 *y = pos % max_height;
545 *x = src_x + (src_y + frame * g->offset_y) / max_height * g->width;
546 *y = (src_y + frame * g->offset_y) % max_height;
549 else /* frames are ordered diagonally */
551 *x = src_x + frame * g->offset_x;
552 *y = src_y + frame * g->offset_y;
556 void getGraphicSource(int graphic, int frame, Bitmap **bitmap, int *x, int *y)
558 getGraphicSourceExt(graphic, frame, bitmap, x, y, FALSE);
561 void DrawGraphic(int x, int y, int graphic, int frame)
564 if (!IN_SCR_FIELD(x, y))
566 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
567 printf("DrawGraphic(): This should never happen!\n");
572 DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic, frame);
576 void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
582 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
583 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
586 void DrawGraphicThruMask(int x, int y, int graphic, int frame)
589 if (!IN_SCR_FIELD(x, y))
591 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
592 printf("DrawGraphicThruMask(): This should never happen!\n");
597 DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY, graphic,
602 void DrawGraphicThruMaskExt(DrawBuffer *d, int dst_x, int dst_y, int graphic,
608 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
610 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
611 dst_x - src_x, dst_y - src_y);
612 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dst_x, dst_y);
615 void DrawMiniGraphic(int x, int y, int graphic)
617 DrawMiniGraphicExt(drawto, SX + x * MINI_TILEX,SY + y * MINI_TILEY, graphic);
618 MarkTileDirty(x / 2, y / 2);
621 void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
623 struct GraphicInfo *g = &graphic_info[graphic];
625 int mini_starty = g->bitmap->height * 2 / 3;
628 *x = mini_startx + g->src_x / 2;
629 *y = mini_starty + g->src_y / 2;
632 void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
637 getMiniGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
638 BlitBitmap(src_bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
641 inline static void DrawGraphicShiftedNormal(int x, int y, int dx, int dy,
642 int graphic, int frame,
643 int cut_mode, int mask_mode)
648 int width = TILEX, height = TILEY;
651 if (dx || dy) /* shifted graphic */
653 if (x < BX1) /* object enters playfield from the left */
660 else if (x > BX2) /* object enters playfield from the right */
666 else if (x==BX1 && dx < 0) /* object leaves playfield to the left */
672 else if (x==BX2 && dx > 0) /* object leaves playfield to the right */
674 else if (dx) /* general horizontal movement */
675 MarkTileDirty(x + SIGN(dx), y);
677 if (y < BY1) /* object enters playfield from the top */
679 if (cut_mode==CUT_BELOW) /* object completely above top border */
687 else if (y > BY2) /* object enters playfield from the bottom */
693 else if (y==BY1 && dy < 0) /* object leaves playfield to the top */
699 else if (dy > 0 && cut_mode == CUT_ABOVE)
701 if (y == BY2) /* object completely above bottom border */
707 MarkTileDirty(x, y + 1);
708 } /* object leaves playfield to the bottom */
709 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
711 else if (dy) /* general vertical movement */
712 MarkTileDirty(x, y + SIGN(dy));
716 if (!IN_SCR_FIELD(x, y))
718 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
719 printf("DrawGraphicShifted(): This should never happen!\n");
724 if (width > 0 && height > 0)
726 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
731 dst_x = FX + x * TILEX + dx;
732 dst_y = FY + y * TILEY + dy;
734 if (mask_mode == USE_MASKING)
736 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
737 dst_x - src_x, dst_y - src_y);
738 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
742 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
749 inline static void DrawGraphicShiftedDouble(int x, int y, int dx, int dy,
750 int graphic, int frame,
751 int cut_mode, int mask_mode)
756 int width = TILEX, height = TILEY;
759 int x2 = x + SIGN(dx);
760 int y2 = y + SIGN(dy);
761 int anim_frames = graphic_info[graphic].anim_frames;
762 int sync_frame = (dx ? ABS(dx) : ABS(dy)) * anim_frames / TILESIZE;
764 /* re-calculate animation frame for two-tile movement animation */
765 frame = getGraphicAnimationFrame(graphic, sync_frame);
767 if (IN_SCR_FIELD(x1, y1)) /* movement start graphic inside screen area */
769 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, TRUE);
771 dst_x = FX + x1 * TILEX;
772 dst_y = FY + y1 * TILEY;
774 if (mask_mode == USE_MASKING)
776 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
777 dst_x - src_x, dst_y - src_y);
778 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
782 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
785 MarkTileDirty(x1, y1);
788 if (IN_SCR_FIELD(x2, y2)) /* movement end graphic inside screen area */
790 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, FALSE);
792 dst_x = FX + x2 * TILEX;
793 dst_y = FY + y2 * TILEY;
795 if (mask_mode == USE_MASKING)
797 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
798 dst_x - src_x, dst_y - src_y);
799 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
803 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
806 MarkTileDirty(x2, y2);
810 printf("::: DONE DrawGraphicShiftedDouble");
816 static void DrawGraphicShifted(int x, int y, int dx, int dy,
817 int graphic, int frame,
818 int cut_mode, int mask_mode)
822 DrawGraphic(x, y, graphic, frame);
827 if (graphic_info[graphic].double_movement) /* EM style movement images */
828 DrawGraphicShiftedDouble(x, y, dx, dy, graphic, frame, cut_mode,mask_mode);
830 DrawGraphicShiftedNormal(x, y, dx, dy, graphic, frame, cut_mode,mask_mode);
833 void DrawGraphicShiftedThruMask(int x, int y, int dx, int dy, int graphic,
834 int frame, int cut_mode)
836 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, USE_MASKING);
839 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
840 int cut_mode, int mask_mode)
842 int lx = LEVELX(x), ly = LEVELY(y);
846 if (IN_LEV_FIELD(lx, ly))
848 SetRandomAnimationValue(lx, ly);
850 graphic = el_act_dir2img(element, GfxAction[lx][ly], GfxDir[lx][ly]);
851 frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
853 /* do not use double (EM style) movement graphic when not moving */
854 if (graphic_info[graphic].double_movement && !dx && !dy)
856 graphic = el_act_dir2img(element, ACTION_DEFAULT, GfxDir[lx][ly]);
857 frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
860 else /* border element */
862 graphic = el2img(element);
863 frame = getGraphicAnimationFrame(graphic, -1);
866 if (element == EL_EXPANDABLE_WALL)
868 boolean left_stopped = FALSE, right_stopped = FALSE;
870 if (!IN_LEV_FIELD(lx - 1, ly) || IS_WALL(Feld[lx - 1][ly]))
872 if (!IN_LEV_FIELD(lx + 1, ly) || IS_WALL(Feld[lx + 1][ly]))
873 right_stopped = TRUE;
875 if (left_stopped && right_stopped)
877 else if (left_stopped)
879 graphic = IMG_EXPANDABLE_WALL_GROWING_RIGHT;
880 frame = graphic_info[graphic].anim_frames - 1;
882 else if (right_stopped)
884 graphic = IMG_EXPANDABLE_WALL_GROWING_LEFT;
885 frame = graphic_info[graphic].anim_frames - 1;
890 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
891 else if (mask_mode == USE_MASKING)
892 DrawGraphicThruMask(x, y, graphic, frame);
894 DrawGraphic(x, y, graphic, frame);
897 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
898 int cut_mode, int mask_mode)
900 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
901 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
902 cut_mode, mask_mode);
905 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
908 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
911 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
914 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
917 void DrawLevelElementThruMask(int x, int y, int element)
919 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
922 void DrawLevelFieldThruMask(int x, int y)
924 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
927 #define TILE_GFX_ELEMENT(x, y) \
928 (GfxElement[x][y] != EL_UNDEFINED && Feld[x][y] != EL_EXPLOSION ? \
929 GfxElement[x][y] : Feld[x][y])
931 static void DrawLevelFieldCrumbledSandExt(int x, int y, int graphic, int frame)
935 int sx = SCREENX(x), sy = SCREENY(y);
937 int width, height, cx, cy, i;
939 int crumbled_border_size = graphic_info[graphic].border_size;
941 int snip = TILEX / 8; /* number of border pixels from "crumbled graphic" */
943 static int xy[4][2] =
952 if (x == 0 && y == 7)
953 printf("::: %d, %d [%d]\n", GfxElement[x][y], Feld[x][y],
954 crumbled_border_size);
957 if (!IN_LEV_FIELD(x, y))
960 element = TILE_GFX_ELEMENT(x, y);
962 /* crumble field itself */
963 if (GFX_CRUMBLED(element) && !IS_MOVING(x, y))
965 if (!IN_SCR_FIELD(sx, sy))
968 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
970 for (i = 0; i < 4; i++)
972 int xx = x + xy[i][0];
973 int yy = y + xy[i][1];
976 element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
979 element = (IN_LEV_FIELD(xx, yy) ? Feld[xx][yy] : BorderElement);
982 /* check if neighbour field is of same type */
983 if (GFX_CRUMBLED(element) && !IS_MOVING(xx, yy))
987 if (Feld[x][y] == EL_CUSTOM_START + 123)
988 printf("::: crumble [%d] THE CHAOS ENGINE (%d, %d): %d, %d\n",
989 i, Feld[x][y], element,
990 GFX_CRUMBLED(element), IS_MOVING(x, y));
993 if (i == 1 || i == 2)
995 width = crumbled_border_size;
997 cx = (i == 2 ? TILEX - crumbled_border_size : 0);
1003 height = crumbled_border_size;
1005 cy = (i == 3 ? TILEY - crumbled_border_size : 0);
1008 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1009 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
1012 MarkTileDirty(sx, sy);
1014 else /* crumble neighbour fields */
1017 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1020 for (i = 0; i < 4; i++)
1022 int xx = x + xy[i][0];
1023 int yy = y + xy[i][1];
1024 int sxx = sx + xy[i][0];
1025 int syy = sy + xy[i][1];
1028 if (!IN_LEV_FIELD(xx, yy) ||
1029 !IN_SCR_FIELD(sxx, syy) ||
1033 element = TILE_GFX_ELEMENT(xx, yy);
1035 if (!GFX_CRUMBLED(element))
1038 if (!IN_LEV_FIELD(xx, yy) ||
1039 !IN_SCR_FIELD(sxx, syy) ||
1040 !GFX_CRUMBLED(Feld[xx][yy]) ||
1046 graphic = el_act2crm(Feld[xx][yy], ACTION_DEFAULT);
1047 crumbled_border_size = graphic_info[graphic].border_size;
1049 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1052 if (i == 1 || i == 2)
1054 width = crumbled_border_size;
1056 cx = (i == 1 ? TILEX - crumbled_border_size : 0);
1062 height = crumbled_border_size;
1064 cy = (i == 0 ? TILEY - crumbled_border_size : 0);
1067 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1068 width, height, FX + sxx * TILEX + cx, FY + syy * TILEY + cy);
1070 MarkTileDirty(sxx, syy);
1075 void DrawLevelFieldCrumbledSand(int x, int y)
1080 if (!IN_LEV_FIELD(x, y))
1083 graphic = el_act2crm(Feld[x][y], ACTION_DEFAULT);
1085 DrawLevelFieldCrumbledSandExt(x, y, graphic, 0);
1087 DrawLevelFieldCrumbledSandExt(x, y, IMG_SAND_CRUMBLED, 0);
1091 void DrawLevelFieldCrumbledSandDigging(int x, int y, int direction,
1095 int graphic1 = el_act_dir2img(GfxElement[x][y], ACTION_DIGGING, direction);
1096 int graphic2 = el_act_dir2crm(GfxElement[x][y], ACTION_DIGGING, direction);
1098 int graphic1 = el_act_dir2img(EL_SAND, ACTION_DIGGING, direction);
1099 int graphic2 = el_act_dir2img(EL_SAND_CRUMBLED, ACTION_DIGGING, direction);
1101 int frame1 = getGraphicAnimationFrame(graphic1, step_frame);
1102 int frame2 = getGraphicAnimationFrame(graphic2, step_frame);
1103 int sx = SCREENX(x), sy = SCREENY(y);
1105 DrawGraphic(sx, sy, graphic1, frame1);
1106 DrawLevelFieldCrumbledSandExt(x, y, graphic2, frame2);
1109 void DrawLevelFieldCrumbledSandNeighbours(int x, int y)
1111 int sx = SCREENX(x), sy = SCREENY(y);
1112 static int xy[4][2] =
1121 for (i = 0; i < 4; i++)
1123 int xx = x + xy[i][0];
1124 int yy = y + xy[i][1];
1125 int sxx = sx + xy[i][0];
1126 int syy = sy + xy[i][1];
1128 if (!IN_LEV_FIELD(xx, yy) ||
1129 !IN_SCR_FIELD(sxx, syy) ||
1130 !GFX_CRUMBLED(Feld[xx][yy]) ||
1134 DrawLevelField(xx, yy);
1138 static int getBorderElement(int x, int y)
1142 { EL_STEELWALL_TOPLEFT, EL_INVISIBLE_STEELWALL_TOPLEFT },
1143 { EL_STEELWALL_TOPRIGHT, EL_INVISIBLE_STEELWALL_TOPRIGHT },
1144 { EL_STEELWALL_BOTTOMLEFT, EL_INVISIBLE_STEELWALL_BOTTOMLEFT },
1145 { EL_STEELWALL_BOTTOMRIGHT, EL_INVISIBLE_STEELWALL_BOTTOMRIGHT },
1146 { EL_STEELWALL_VERTICAL, EL_INVISIBLE_STEELWALL_VERTICAL },
1147 { EL_STEELWALL_HORIZONTAL, EL_INVISIBLE_STEELWALL_HORIZONTAL },
1148 { EL_STEELWALL, EL_INVISIBLE_STEELWALL }
1150 int steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
1151 int steel_position = (x == -1 && y == -1 ? 0 :
1152 x == lev_fieldx && y == -1 ? 1 :
1153 x == -1 && y == lev_fieldy ? 2 :
1154 x == lev_fieldx && y == lev_fieldy ? 3 :
1155 x == -1 || x == lev_fieldx ? 4 :
1156 y == -1 || y == lev_fieldy ? 5 : 6);
1158 return border[steel_position][steel_type];
1161 void DrawScreenElement(int x, int y, int element)
1163 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1164 DrawLevelFieldCrumbledSand(LEVELX(x), LEVELY(y));
1167 void DrawLevelElement(int x, int y, int element)
1169 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1170 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1173 void DrawScreenField(int x, int y)
1175 int lx = LEVELX(x), ly = LEVELY(y);
1176 int element, content;
1178 if (!IN_LEV_FIELD(lx, ly))
1180 if (lx < -1 || lx > lev_fieldx || ly < -1 || ly > lev_fieldy)
1183 element = getBorderElement(lx, ly);
1185 DrawScreenElement(x, y, element);
1189 element = Feld[lx][ly];
1190 content = Store[lx][ly];
1192 if (IS_MOVING(lx, ly))
1194 int horiz_move = (MovDir[lx][ly] == MV_LEFT || MovDir[lx][ly] == MV_RIGHT);
1195 boolean cut_mode = NO_CUTTING;
1197 if (element == EL_QUICKSAND_EMPTYING ||
1198 element == EL_MAGIC_WALL_EMPTYING ||
1199 element == EL_BD_MAGIC_WALL_EMPTYING ||
1200 element == EL_AMOEBA_DROPPING)
1201 cut_mode = CUT_ABOVE;
1202 else if (element == EL_QUICKSAND_FILLING ||
1203 element == EL_MAGIC_WALL_FILLING ||
1204 element == EL_BD_MAGIC_WALL_FILLING)
1205 cut_mode = CUT_BELOW;
1207 if (cut_mode == CUT_ABOVE)
1208 DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1210 DrawScreenElement(x, y, EL_EMPTY);
1213 DrawScreenElementShifted(x, y, MovPos[lx][ly], 0, element, NO_CUTTING);
1214 else if (cut_mode == NO_CUTTING)
1215 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], element, cut_mode);
1217 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], content, cut_mode);
1219 if (content == EL_ACID)
1221 int dir = MovDir[lx][ly];
1222 int newlx = lx + (dir == MV_LEFT ? -1 : dir == MV_RIGHT ? +1 : 0);
1223 int newly = ly + (dir == MV_UP ? -1 : dir == MV_DOWN ? +1 : 0);
1225 DrawLevelElementThruMask(newlx, newly, EL_ACID);
1228 else if (IS_BLOCKED(lx, ly))
1233 boolean cut_mode = NO_CUTTING;
1234 int element_old, content_old;
1236 Blocked2Moving(lx, ly, &oldx, &oldy);
1239 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1240 MovDir[oldx][oldy] == MV_RIGHT);
1242 element_old = Feld[oldx][oldy];
1243 content_old = Store[oldx][oldy];
1245 if (element_old == EL_QUICKSAND_EMPTYING ||
1246 element_old == EL_MAGIC_WALL_EMPTYING ||
1247 element_old == EL_BD_MAGIC_WALL_EMPTYING ||
1248 element_old == EL_AMOEBA_DROPPING)
1249 cut_mode = CUT_ABOVE;
1251 DrawScreenElement(x, y, EL_EMPTY);
1254 DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
1256 else if (cut_mode == NO_CUTTING)
1257 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
1260 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
1263 else if (IS_DRAWABLE(element))
1264 DrawScreenElement(x, y, element);
1266 DrawScreenElement(x, y, EL_EMPTY);
1269 void DrawLevelField(int x, int y)
1271 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1272 DrawScreenField(SCREENX(x), SCREENY(y));
1273 else if (IS_MOVING(x, y))
1277 Moving2Blocked(x, y, &newx, &newy);
1278 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1279 DrawScreenField(SCREENX(newx), SCREENY(newy));
1281 else if (IS_BLOCKED(x, y))
1285 Blocked2Moving(x, y, &oldx, &oldy);
1286 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1287 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1291 void DrawMiniElement(int x, int y, int element)
1295 graphic = el2edimg(element);
1296 DrawMiniGraphic(x, y, graphic);
1299 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1301 int x = sx + scroll_x, y = sy + scroll_y;
1303 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1304 DrawMiniElement(sx, sy, EL_EMPTY);
1305 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1306 DrawMiniElement(sx, sy, Feld[x][y]);
1308 DrawMiniGraphic(sx, sy, el2edimg(getBorderElement(x, y)));
1311 void DrawEnvelopeBackground(int envelope_nr, int startx, int starty,
1312 int x, int y, int xsize, int ysize, int font_nr)
1314 int font_width = getFontWidth(font_nr);
1315 int font_height = getFontHeight(font_nr);
1316 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1319 int dst_x = SX + startx + x * font_width;
1320 int dst_y = SY + starty + y * font_height;
1321 int width = graphic_info[graphic].width;
1322 int height = graphic_info[graphic].height;
1323 int inner_width = MAX(width - 2 * font_width, font_width);
1324 int inner_height = MAX(height - 2 * font_height, font_height);
1325 int inner_sx = (width >= 3 * font_width ? font_width : 0);
1326 int inner_sy = (height >= 3 * font_height ? font_height : 0);
1327 boolean draw_masked = graphic_info[graphic].draw_masked;
1329 getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
1331 if (src_bitmap == NULL || width < font_width || height < font_height)
1333 ClearRectangle(drawto, dst_x, dst_y, font_width, font_height);
1337 src_x += (x == 0 ? 0 : x == xsize - 1 ? width - font_width :
1338 inner_sx + (x - 1) * font_width % inner_width);
1339 src_y += (y == 0 ? 0 : y == ysize - 1 ? height - font_height :
1340 inner_sy + (y - 1) * font_height % inner_height);
1344 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1345 dst_x - src_x, dst_y - src_y);
1346 BlitBitmapMasked(src_bitmap, drawto, src_x, src_y, font_width, font_height,
1350 BlitBitmap(src_bitmap, drawto, src_x, src_y, font_width, font_height,
1354 void AnimateEnvelope(int envelope_nr, int anim_mode, int action)
1356 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1358 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
1359 int mask_mode = (src_bitmap != NULL ? BLIT_MASKED : BLIT_ON_BACKGROUND);
1361 boolean draw_masked = graphic_info[graphic].draw_masked;
1362 int mask_mode = (draw_masked ? BLIT_MASKED : BLIT_ON_BACKGROUND);
1364 boolean ffwd_delay = (tape.playing && tape.fast_forward);
1365 boolean no_delay = (tape.warp_forward);
1366 unsigned long anim_delay = 0;
1367 int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
1368 int anim_delay_value = (no_delay ? 0 : frame_delay_value);
1369 int font_nr = FONT_ENVELOPE_1 + envelope_nr;
1370 int font_width = getFontWidth(font_nr);
1371 int font_height = getFontHeight(font_nr);
1372 int max_xsize = level.envelope_xsize[envelope_nr];
1373 int max_ysize = level.envelope_ysize[envelope_nr];
1374 int xstart = (anim_mode & ANIM_VERTICAL ? max_xsize : 0);
1375 int ystart = (anim_mode & ANIM_HORIZONTAL ? max_ysize : 0);
1376 int xend = max_xsize;
1377 int yend = (anim_mode != ANIM_DEFAULT ? max_ysize : 0);
1378 int xstep = (xstart < xend ? 1 : 0);
1379 int ystep = (ystart < yend || xstep == 0 ? 1 : 0);
1382 for (x = xstart, y = ystart; x <= xend && y <= yend; x += xstep, y += ystep)
1384 int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2;
1385 int ysize = (action == ACTION_CLOSING ? yend - (y - ystart) : y) + 2;
1386 int sx = (SXSIZE - xsize * font_width) / 2;
1387 int sy = (SYSIZE - ysize * font_height) / 2;
1390 SetDrawtoField(DRAW_BUFFERED);
1392 BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
1394 SetDrawtoField(DRAW_BACKBUFFER);
1396 for (yy = 0; yy < ysize; yy++) for (xx = 0; xx < xsize; xx++)
1397 DrawEnvelopeBackground(envelope_nr, sx,sy, xx,yy, xsize, ysize, font_nr);
1399 DrawTextToTextArea(SX + sx + font_width, SY + sy + font_height,
1400 level.envelope_text[envelope_nr], font_nr, max_xsize,
1401 xsize - 2, ysize - 2, mask_mode);
1403 redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
1406 WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
1410 void ShowEnvelope(int envelope_nr)
1412 int element = EL_ENVELOPE_1 + envelope_nr;
1413 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1414 int sound_opening = element_info[element].sound[ACTION_OPENING];
1415 int sound_closing = element_info[element].sound[ACTION_CLOSING];
1416 boolean ffwd_delay = (tape.playing && tape.fast_forward);
1417 boolean no_delay = (tape.warp_forward);
1418 int normal_delay_value = ONE_SECOND_DELAY / (ffwd_delay ? 2 : 1);
1419 int wait_delay_value = (no_delay ? 0 : normal_delay_value);
1420 int anim_mode = graphic_info[graphic].anim_mode;
1421 int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL:
1422 anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode);
1424 game.envelope_active = TRUE; /* needed for RedrawPlayfield() events */
1426 PlaySoundStereo(sound_opening, SOUND_MIDDLE);
1428 if (anim_mode == ANIM_DEFAULT)
1429 AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_OPENING);
1431 AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_OPENING);
1434 Delay(wait_delay_value);
1436 WaitForEventToContinue();
1438 PlaySoundStereo(sound_closing, SOUND_MIDDLE);
1440 if (anim_mode != ANIM_NONE)
1441 AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_CLOSING);
1443 if (anim_mode == ANIM_DEFAULT)
1444 AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_CLOSING);
1446 game.envelope_active = FALSE;
1448 SetDrawtoField(DRAW_BUFFERED);
1450 redraw_mask |= REDRAW_FIELD;
1454 void getMicroGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1456 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
1457 int mini_startx = src_bitmap->width * 3 / 4;
1458 int mini_starty = src_bitmap->height * 2 / 3;
1459 int src_x = mini_startx + graphic_info[graphic].src_x / 8;
1460 int src_y = mini_starty + graphic_info[graphic].src_y / 8;
1462 *bitmap = src_bitmap;
1467 void DrawMicroElement(int xpos, int ypos, int element)
1471 int graphic = el2preimg(element);
1473 getMicroGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1474 BlitBitmap(src_bitmap, drawto, src_x, src_y, MICRO_TILEX, MICRO_TILEY,
1482 SetDrawBackgroundMask(REDRAW_NONE);
1485 for (x = BX1; x <= BX2; x++)
1486 for (y = BY1; y <= BY2; y++)
1487 DrawScreenField(x, y);
1489 redraw_mask |= REDRAW_FIELD;
1492 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1496 for (x = 0; x < size_x; x++)
1497 for (y = 0; y < size_y; y++)
1498 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1500 redraw_mask |= REDRAW_FIELD;
1503 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1507 DrawBackground(xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
1509 if (lev_fieldx < STD_LEV_FIELDX)
1510 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1511 if (lev_fieldy < STD_LEV_FIELDY)
1512 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1514 xpos += MICRO_TILEX;
1515 ypos += MICRO_TILEY;
1517 for (x = -1; x <= STD_LEV_FIELDX; x++)
1519 for (y = -1; y <= STD_LEV_FIELDY; y++)
1521 int lx = from_x + x, ly = from_y + y;
1523 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1524 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1525 level.field[lx][ly]);
1526 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1
1527 && BorderElement != EL_EMPTY)
1528 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1529 getBorderElement(lx, ly));
1533 redraw_mask |= REDRAW_MICROLEVEL;
1536 #define MICROLABEL_EMPTY 0
1537 #define MICROLABEL_LEVEL_NAME 1
1538 #define MICROLABEL_CREATED_BY 2
1539 #define MICROLABEL_LEVEL_AUTHOR 3
1540 #define MICROLABEL_IMPORTED_FROM 4
1541 #define MICROLABEL_LEVEL_IMPORT_INFO 5
1543 static void DrawMicroLevelLabelExt(int mode)
1545 char label_text[MAX_OUTPUT_LINESIZE + 1];
1546 int max_len_label_text;
1547 int font_nr = FONT_TEXT_2;
1549 if (mode == MICROLABEL_CREATED_BY || mode == MICROLABEL_IMPORTED_FROM)
1550 font_nr = FONT_TEXT_3;
1552 max_len_label_text = SXSIZE / getFontWidth(font_nr);
1554 DrawBackground(SX, MICROLABEL_YPOS, SXSIZE, getFontHeight(font_nr));
1556 strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
1557 mode == MICROLABEL_CREATED_BY ? "created by" :
1558 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
1559 mode == MICROLABEL_IMPORTED_FROM ? "imported from" :
1560 mode == MICROLABEL_LEVEL_IMPORT_INFO ?
1561 leveldir_current->imported_from : ""),
1562 max_len_label_text);
1563 label_text[max_len_label_text] = '\0';
1565 if (strlen(label_text) > 0)
1567 int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
1568 int lypos = MICROLABEL_YPOS;
1570 DrawText(lxpos, lypos, label_text, font_nr);
1573 redraw_mask |= REDRAW_MICROLEVEL;
1576 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1578 static unsigned long scroll_delay = 0;
1579 static unsigned long label_delay = 0;
1580 static int from_x, from_y, scroll_direction;
1581 static int label_state, label_counter;
1582 int last_game_status = game_status; /* save current game status */
1584 /* force PREVIEW font on preview level */
1585 game_status = GAME_MODE_PSEUDO_PREVIEW;
1589 from_x = from_y = 0;
1590 scroll_direction = MV_RIGHT;
1594 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1595 DrawMicroLevelLabelExt(label_state);
1597 /* initialize delay counters */
1598 DelayReached(&scroll_delay, 0);
1599 DelayReached(&label_delay, 0);
1601 if (leveldir_current->name)
1603 int text_width = getTextWidth(leveldir_current->name, FONT_TEXT_1);
1604 int lxpos = SX + (SXSIZE - text_width) / 2;
1605 int lypos = SY + 352;
1607 DrawText(lxpos, lypos, leveldir_current->name, FONT_TEXT_1);
1610 game_status = last_game_status; /* restore current game status */
1615 /* scroll micro level, if needed */
1616 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1617 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1619 switch (scroll_direction)
1625 scroll_direction = MV_UP;
1629 if (from_x < lev_fieldx - STD_LEV_FIELDX)
1632 scroll_direction = MV_DOWN;
1639 scroll_direction = MV_RIGHT;
1643 if (from_y < lev_fieldy - STD_LEV_FIELDY)
1646 scroll_direction = MV_LEFT;
1653 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1656 /* redraw micro level label, if needed */
1657 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1658 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1659 strcmp(level.author, leveldir_current->name) != 0 &&
1660 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1662 int max_label_counter = 23;
1664 if (leveldir_current->imported_from != NULL)
1665 max_label_counter += 14;
1667 label_counter = (label_counter + 1) % max_label_counter;
1668 label_state = (label_counter >= 0 && label_counter <= 7 ?
1669 MICROLABEL_LEVEL_NAME :
1670 label_counter >= 9 && label_counter <= 12 ?
1671 MICROLABEL_CREATED_BY :
1672 label_counter >= 14 && label_counter <= 21 ?
1673 MICROLABEL_LEVEL_AUTHOR :
1674 label_counter >= 23 && label_counter <= 26 ?
1675 MICROLABEL_IMPORTED_FROM :
1676 label_counter >= 28 && label_counter <= 35 ?
1677 MICROLABEL_LEVEL_IMPORT_INFO : MICROLABEL_EMPTY);
1678 DrawMicroLevelLabelExt(label_state);
1681 game_status = last_game_status; /* restore current game status */
1684 inline void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
1685 int graphic, int sync_frame, int mask_mode)
1687 int frame = getGraphicAnimationFrame(graphic, sync_frame);
1689 if (mask_mode == USE_MASKING)
1690 DrawGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
1692 DrawGraphicExt(dst_bitmap, x, y, graphic, frame);
1695 inline void DrawGraphicAnimation(int x, int y, int graphic)
1697 int lx = LEVELX(x), ly = LEVELY(y);
1699 if (!IN_SCR_FIELD(x, y))
1702 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
1703 graphic, GfxFrame[lx][ly], NO_MASKING);
1704 MarkTileDirty(x, y);
1707 void DrawLevelGraphicAnimation(int x, int y, int graphic)
1709 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
1712 void DrawLevelElementAnimation(int x, int y, int element)
1715 int graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
1717 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
1719 DrawGraphicAnimation(SCREENX(x), SCREENY(y), el2img(element));
1723 inline void DrawLevelGraphicAnimationIfNeeded(int x, int y, int graphic)
1725 int sx = SCREENX(x), sy = SCREENY(y);
1727 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
1730 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
1733 DrawGraphicAnimation(sx, sy, graphic);
1735 if (GFX_CRUMBLED(Feld[x][y]))
1736 DrawLevelFieldCrumbledSand(x, y);
1739 void DrawLevelElementAnimationIfNeeded(int x, int y, int element)
1741 int sx = SCREENX(x), sy = SCREENY(y);
1744 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
1747 graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
1749 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
1752 DrawGraphicAnimation(sx, sy, graphic);
1754 if (GFX_CRUMBLED(element))
1755 DrawLevelFieldCrumbledSand(x, y);
1758 static int getPlayerGraphic(struct PlayerInfo *player, int move_dir)
1760 if (player->use_murphy_graphic)
1762 /* this works only because currently only one player can be "murphy" ... */
1763 static int last_horizontal_dir = MV_LEFT;
1764 int graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, move_dir);
1766 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
1767 last_horizontal_dir = move_dir;
1769 if (graphic == IMG_SP_MURPHY) /* undefined => use special graphic */
1771 int direction = (player->is_snapping ? move_dir : last_horizontal_dir);
1773 graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, direction);
1779 return el_act_dir2img(player->element_nr, player->GfxAction, move_dir);
1782 static boolean equalGraphics(int graphic1, int graphic2)
1784 struct GraphicInfo *g1 = &graphic_info[graphic1];
1785 struct GraphicInfo *g2 = &graphic_info[graphic2];
1787 return (g1->bitmap == g2->bitmap &&
1788 g1->src_x == g2->src_x &&
1789 g1->src_y == g2->src_y &&
1790 g1->anim_frames == g2->anim_frames &&
1791 g1->anim_delay == g2->anim_delay &&
1792 g1->anim_mode == g2->anim_mode);
1795 void DrawAllPlayers()
1799 for (i = 0; i < MAX_PLAYERS; i++)
1800 if (stored_player[i].active)
1801 DrawPlayer(&stored_player[i]);
1804 void DrawPlayerField(int x, int y)
1806 if (!IS_PLAYER(x, y))
1809 DrawPlayer(PLAYERINFO(x, y));
1812 void DrawPlayer(struct PlayerInfo *player)
1814 int jx = player->jx;
1815 int jy = player->jy;
1816 int move_dir = player->MovDir;
1818 int last_jx = player->last_jx;
1819 int last_jy = player->last_jy;
1820 int next_jx = jx + (jx - last_jx);
1821 int next_jy = jy + (jy - last_jy);
1822 boolean player_is_moving = (last_jx != jx || last_jy != jy ? TRUE : FALSE);
1824 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? +1 : 0);
1825 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? +1 : 0);
1826 int last_jx = (player->is_moving ? jx - dx : jx);
1827 int last_jy = (player->is_moving ? jy - dy : jy);
1828 int next_jx = jx + dx;
1829 int next_jy = jy + dy;
1830 boolean player_is_moving = (player->MovPos ? TRUE : FALSE);
1832 int sx = SCREENX(jx), sy = SCREENY(jy);
1833 int sxx = 0, syy = 0;
1834 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
1836 int action = ACTION_DEFAULT;
1837 int last_player_graphic = getPlayerGraphic(player, move_dir);
1838 int last_player_frame = player->Frame;
1841 if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
1845 if (!IN_LEV_FIELD(jx, jy))
1847 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
1848 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
1849 printf("DrawPlayerField(): This should never happen!\n");
1854 if (element == EL_EXPLOSION)
1857 action = (player->is_pushing ? ACTION_PUSHING :
1858 player->is_digging ? ACTION_DIGGING :
1859 player->is_collecting ? ACTION_COLLECTING :
1860 player->is_moving ? ACTION_MOVING :
1861 player->is_snapping ? ACTION_SNAPPING :
1862 player->is_dropping ? ACTION_DROPPING :
1863 player->is_waiting ? player->action_waiting : ACTION_DEFAULT);
1865 InitPlayerGfxAnimation(player, action, move_dir);
1867 /* ----------------------------------------------------------------------- */
1868 /* draw things in the field the player is leaving, if needed */
1869 /* ----------------------------------------------------------------------- */
1872 if (player->is_moving)
1874 if (player_is_moving)
1877 if (Back[last_jx][last_jy] && IS_DRAWABLE(last_element))
1879 DrawLevelElement(last_jx, last_jy, Back[last_jx][last_jy]);
1881 if (last_element == EL_DYNAMITE_ACTIVE ||
1882 last_element == EL_SP_DISK_RED_ACTIVE)
1883 DrawDynamite(last_jx, last_jy);
1885 DrawLevelFieldThruMask(last_jx, last_jy);
1887 else if (last_element == EL_DYNAMITE_ACTIVE ||
1888 last_element == EL_SP_DISK_RED_ACTIVE)
1889 DrawDynamite(last_jx, last_jy);
1891 DrawLevelField(last_jx, last_jy);
1893 if (player->is_pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
1894 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
1897 if (!IN_SCR_FIELD(sx, sy))
1900 if (setup.direct_draw)
1901 SetDrawtoField(DRAW_BUFFERED);
1903 /* ----------------------------------------------------------------------- */
1904 /* draw things behind the player, if needed */
1905 /* ----------------------------------------------------------------------- */
1908 DrawLevelElement(jx, jy, Back[jx][jy]);
1909 else if (IS_ACTIVE_BOMB(element))
1910 DrawLevelElement(jx, jy, EL_EMPTY);
1913 if (player_is_moving && GfxElement[jx][jy] != EL_UNDEFINED)
1915 if (GFX_CRUMBLED(GfxElement[jx][jy]))
1916 DrawLevelFieldCrumbledSandDigging(jx, jy, move_dir, player->StepFrame);
1919 int old_element = GfxElement[jx][jy];
1920 int old_graphic = el_act_dir2img(old_element, action, move_dir);
1921 int frame = getGraphicAnimationFrame(old_graphic, player->StepFrame);
1923 DrawGraphic(sx, sy, old_graphic, frame);
1928 GfxElement[jx][jy] = EL_UNDEFINED;
1930 DrawLevelField(jx, jy);
1934 /* ----------------------------------------------------------------------- */
1935 /* draw player himself */
1936 /* ----------------------------------------------------------------------- */
1940 graphic = getPlayerGraphic(player, move_dir);
1942 /* in the case of changed player action or direction, prevent the current
1943 animation frame from being restarted for identical animations */
1944 if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic))
1945 player->Frame = last_player_frame;
1949 if (player->use_murphy_graphic)
1951 static int last_horizontal_dir = MV_LEFT;
1953 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
1954 last_horizontal_dir = move_dir;
1956 graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, move_dir);
1958 if (graphic == IMG_SP_MURPHY) /* undefined => use special graphic */
1960 int direction = (player->is_snapping ? move_dir : last_horizontal_dir);
1962 graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, direction);
1966 graphic = el_act_dir2img(player->element_nr, player->GfxAction, move_dir);
1970 frame = getGraphicAnimationFrame(graphic, player->Frame);
1974 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
1975 sxx = player->GfxPos;
1977 syy = player->GfxPos;
1980 if (!setup.soft_scrolling && ScreenMovPos)
1983 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
1985 if (SHIELD_ON(player))
1987 int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
1988 IMG_SHIELD_NORMAL_ACTIVE);
1989 int frame = getGraphicAnimationFrame(graphic, -1);
1991 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
1994 /* ----------------------------------------------------------------------- */
1995 /* draw things the player is pushing, if needed */
1996 /* ----------------------------------------------------------------------- */
1999 printf("::: %d, %d [%d, %d] [%d]\n",
2000 player->is_pushing, player_is_moving, player->GfxAction,
2001 player->is_moving, player_is_moving);
2005 if (player->is_pushing && player->is_moving)
2007 if (player->is_pushing && player_is_moving)
2011 int px = SCREENX(jx), py = SCREENY(jy);
2012 int pxx = (TILEX - ABS(sxx)) * dx;
2013 int pyy = (TILEY - ABS(syy)) * dy;
2015 int px = SCREENX(next_jx), py = SCREENY(next_jy);
2024 if (!IS_MOVING(jx, jy)) /* push movement already finished */
2025 element = Feld[next_jx][next_jy];
2027 graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
2028 frame = getGraphicAnimationFrame(graphic, player->StepFrame);
2030 if (Back[next_jx][next_jy])
2031 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
2033 /* masked drawing is needed for EMC style (double) movement graphics */
2034 DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame, NO_CUTTING);
2037 if (Back[next_jx][next_jy])
2038 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
2040 if ((pxx || pyy) && element == EL_SOKOBAN_OBJECT)
2041 DrawGraphicShiftedThruMask(px, py, pxx, pyy, IMG_SOKOBAN_OBJECT, 0,
2045 int element = MovingOrBlocked2Element(next_jx, next_jy);
2046 int graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
2048 int frame = getGraphicAnimationFrame(graphic, player->StepFrame);
2050 int frame = getGraphicAnimationFrame(graphic, player->Frame);
2054 /* masked drawing is needed for EMC style (double) movement graphics */
2055 DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame,
2058 DrawGraphicShifted(px, py, pxx, pyy, graphic, frame,
2059 NO_CUTTING, NO_MASKING);
2065 /* ----------------------------------------------------------------------- */
2066 /* draw things in front of player (active dynamite or dynabombs) */
2067 /* ----------------------------------------------------------------------- */
2069 if (IS_ACTIVE_BOMB(element))
2071 graphic = el2img(element);
2072 frame = getGraphicAnimationFrame(graphic, GfxFrame[jx][jy]);
2074 if (game.emulation == EMU_SUPAPLEX)
2075 DrawGraphic(sx, sy, IMG_SP_DISK_RED, frame);
2077 DrawGraphicThruMask(sx, sy, graphic, frame);
2080 if (player_is_moving && last_element == EL_EXPLOSION)
2082 int graphic = el_act2img(GfxElement[last_jx][last_jy], ACTION_EXPLODING);
2083 int delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2);
2084 int phase = ExplodePhase[last_jx][last_jy] - 1;
2085 int frame = getGraphicAnimationFrame(graphic, phase - delay);
2088 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy), graphic, frame);
2091 /* ----------------------------------------------------------------------- */
2092 /* draw elements the player is just walking/passing through/under */
2093 /* ----------------------------------------------------------------------- */
2095 if (player_is_moving)
2097 /* handle the field the player is leaving ... */
2098 if (IS_ACCESSIBLE_INSIDE(last_element))
2099 DrawLevelField(last_jx, last_jy);
2100 else if (IS_ACCESSIBLE_UNDER(last_element))
2101 DrawLevelFieldThruMask(last_jx, last_jy);
2105 /* do not redraw accessible elements if the player is just pushing them */
2106 if (!player_is_moving || !player->is_pushing)
2108 /* ... and the field the player is entering */
2109 if (IS_ACCESSIBLE_INSIDE(element))
2110 DrawLevelField(jx, jy);
2111 else if (IS_ACCESSIBLE_UNDER(element))
2112 DrawLevelFieldThruMask(jx, jy);
2118 /* !!! I have forgotton what this should be good for !!! */
2119 /* !!! causes player being visible when pushing from within tubes !!! */
2120 if (!player->is_pushing)
2123 /* ... and the field the player is entering */
2124 if (IS_ACCESSIBLE_INSIDE(element))
2125 DrawLevelField(jx, jy);
2126 else if (IS_ACCESSIBLE_UNDER(element))
2127 DrawLevelFieldThruMask(jx, jy);
2131 if (setup.direct_draw)
2133 int dst_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
2134 int dst_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
2135 int x_size = TILEX * (1 + ABS(jx - last_jx));
2136 int y_size = TILEY * (1 + ABS(jy - last_jy));
2138 BlitBitmap(drawto_field, window,
2139 dst_x, dst_y, x_size, y_size, dst_x, dst_y);
2140 SetDrawtoField(DRAW_DIRECT);
2143 MarkTileDirty(sx, sy);
2146 /* ------------------------------------------------------------------------- */
2148 void WaitForEventToContinue()
2150 boolean still_wait = TRUE;
2152 /* simulate releasing mouse button over last gadget, if still pressed */
2154 HandleGadgets(-1, -1, 0);
2156 button_status = MB_RELEASED;
2168 case EVENT_BUTTONPRESS:
2169 case EVENT_KEYPRESS:
2173 case EVENT_KEYRELEASE:
2174 ClearPlayerAction();
2178 HandleOtherEvents(&event);
2182 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2189 /* don't eat all CPU time */
2194 #define MAX_REQUEST_LINES 13
2195 #define MAX_REQUEST_LINE_FONT1_LEN 7
2196 #define MAX_REQUEST_LINE_FONT2_LEN 10
2198 boolean Request(char *text, unsigned int req_state)
2200 int mx, my, ty, result = -1;
2201 unsigned int old_door_state;
2202 int last_game_status = game_status; /* save current game status */
2203 int max_request_line_len = MAX_REQUEST_LINE_FONT1_LEN;
2204 int font_nr = FONT_TEXT_2;
2205 int max_word_len = 0;
2208 for (text_ptr = text; *text_ptr; text_ptr++)
2210 max_word_len = (*text_ptr != ' ' ? max_word_len + 1 : 0);
2212 if (max_word_len > MAX_REQUEST_LINE_FONT1_LEN)
2214 max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
2215 font_nr = FONT_LEVEL_NUMBER;
2222 /* disable deactivated drawing when quick-loading level tape recording */
2223 if (tape.playing && tape.deactivate_display)
2224 TapeDeactivateDisplayOff(TRUE);
2228 SetMouseCursor(CURSOR_DEFAULT);
2231 #if defined(NETWORK_AVALIABLE)
2232 /* pause network game while waiting for request to answer */
2233 if (options.network &&
2234 game_status == GAME_MODE_PLAYING &&
2235 req_state & REQUEST_WAIT_FOR_INPUT)
2236 SendToServer_PausePlaying();
2239 old_door_state = GetDoorState();
2241 /* simulate releasing mouse button over last gadget, if still pressed */
2243 HandleGadgets(-1, -1, 0);
2247 if (old_door_state & DOOR_OPEN_1)
2249 CloseDoor(DOOR_CLOSE_1);
2251 /* save old door content */
2252 BlitBitmap(bitmap_db_door, bitmap_db_door,
2253 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
2254 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
2257 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
2259 /* clear door drawing field */
2260 DrawBackground(DX, DY, DXSIZE, DYSIZE);
2262 /* force DOOR font on preview level */
2263 game_status = GAME_MODE_PSEUDO_DOOR;
2265 /* write text for request */
2266 for (ty = 0; ty < MAX_REQUEST_LINES; ty++)
2268 char text_line[max_request_line_len + 1];
2274 for (tl = 0, tx = 0; tx < max_request_line_len; tl++, tx++)
2277 if (!tc || tc == ' ')
2288 strncpy(text_line, text, tl);
2291 DrawText(DX + (DXSIZE - tl * getFontWidth(font_nr)) / 2,
2292 DY + 8 + ty * (getFontHeight(font_nr) + 2),
2293 text_line, font_nr);
2295 text += tl + (tc == ' ' ? 1 : 0);
2298 game_status = last_game_status; /* restore current game status */
2300 if (req_state & REQ_ASK)
2302 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
2303 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
2305 else if (req_state & REQ_CONFIRM)
2307 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
2309 else if (req_state & REQ_PLAYER)
2311 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
2312 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
2313 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
2314 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
2317 /* copy request gadgets to door backbuffer */
2318 BlitBitmap(drawto, bitmap_db_door,
2319 DX, DY, DXSIZE, DYSIZE,
2320 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2322 OpenDoor(DOOR_OPEN_1);
2328 if (!(req_state & REQUEST_WAIT_FOR_INPUT))
2330 SetDrawBackgroundMask(REDRAW_FIELD);
2335 if (game_status != GAME_MODE_MAIN)
2338 button_status = MB_RELEASED;
2340 request_gadget_id = -1;
2342 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
2345 SetMouseCursor(CURSOR_DEFAULT);
2358 case EVENT_BUTTONPRESS:
2359 case EVENT_BUTTONRELEASE:
2360 case EVENT_MOTIONNOTIFY:
2362 if (event.type == EVENT_MOTIONNOTIFY)
2364 if (!PointerInWindow(window))
2365 continue; /* window and pointer are on different screens */
2370 motion_status = TRUE;
2371 mx = ((MotionEvent *) &event)->x;
2372 my = ((MotionEvent *) &event)->y;
2376 motion_status = FALSE;
2377 mx = ((ButtonEvent *) &event)->x;
2378 my = ((ButtonEvent *) &event)->y;
2379 if (event.type == EVENT_BUTTONPRESS)
2380 button_status = ((ButtonEvent *) &event)->button;
2382 button_status = MB_RELEASED;
2385 /* this sets 'request_gadget_id' */
2386 HandleGadgets(mx, my, button_status);
2388 switch(request_gadget_id)
2390 case TOOL_CTRL_ID_YES:
2393 case TOOL_CTRL_ID_NO:
2396 case TOOL_CTRL_ID_CONFIRM:
2397 result = TRUE | FALSE;
2400 case TOOL_CTRL_ID_PLAYER_1:
2403 case TOOL_CTRL_ID_PLAYER_2:
2406 case TOOL_CTRL_ID_PLAYER_3:
2409 case TOOL_CTRL_ID_PLAYER_4:
2420 case EVENT_KEYPRESS:
2421 switch(GetEventKey((KeyEvent *)&event, TRUE))
2434 if (req_state & REQ_PLAYER)
2438 case EVENT_KEYRELEASE:
2439 ClearPlayerAction();
2443 HandleOtherEvents(&event);
2447 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2449 int joy = AnyJoystick();
2451 if (joy & JOY_BUTTON_1)
2453 else if (joy & JOY_BUTTON_2)
2459 /* don't eat all CPU time */
2463 if (game_status != GAME_MODE_MAIN)
2468 if (!(req_state & REQ_STAY_OPEN))
2470 CloseDoor(DOOR_CLOSE_1);
2472 if (((old_door_state & DOOR_OPEN_1) && !(req_state & REQ_STAY_CLOSED)) ||
2473 (req_state & REQ_REOPEN))
2474 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
2479 SetDrawBackgroundMask(REDRAW_FIELD);
2481 #if defined(NETWORK_AVALIABLE)
2482 /* continue network game after request */
2483 if (options.network &&
2484 game_status == GAME_MODE_PLAYING &&
2485 req_state & REQUEST_WAIT_FOR_INPUT)
2486 SendToServer_ContinuePlaying();
2490 /* restore deactivated drawing when quick-loading level tape recording */
2491 if (tape.playing && tape.deactivate_display)
2492 TapeDeactivateDisplayOn();
2498 unsigned int OpenDoor(unsigned int door_state)
2500 if (door_state & DOOR_COPY_BACK)
2502 if (door_state & DOOR_OPEN_1)
2503 BlitBitmap(bitmap_db_door, bitmap_db_door,
2504 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
2505 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2507 if (door_state & DOOR_OPEN_2)
2508 BlitBitmap(bitmap_db_door, bitmap_db_door,
2509 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY2, VXSIZE, VYSIZE,
2510 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2512 door_state &= ~DOOR_COPY_BACK;
2515 return MoveDoor(door_state);
2518 unsigned int CloseDoor(unsigned int door_state)
2520 unsigned int old_door_state = GetDoorState();
2522 if (!(door_state & DOOR_NO_COPY_BACK))
2524 if (old_door_state & DOOR_OPEN_1)
2525 BlitBitmap(backbuffer, bitmap_db_door,
2526 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2528 if (old_door_state & DOOR_OPEN_2)
2529 BlitBitmap(backbuffer, bitmap_db_door,
2530 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2532 door_state &= ~DOOR_NO_COPY_BACK;
2535 return MoveDoor(door_state);
2538 unsigned int GetDoorState()
2540 return MoveDoor(DOOR_GET_STATE);
2543 unsigned int SetDoorState(unsigned int door_state)
2545 return MoveDoor(door_state | DOOR_SET_STATE);
2548 unsigned int MoveDoor(unsigned int door_state)
2550 static int door1 = DOOR_OPEN_1;
2551 static int door2 = DOOR_CLOSE_2;
2552 unsigned long door_delay = 0;
2553 unsigned long door_delay_value;
2556 if (door_state == DOOR_GET_STATE)
2557 return(door1 | door2);
2559 if (door_state & DOOR_SET_STATE)
2561 if (door_state & DOOR_ACTION_1)
2562 door1 = door_state & DOOR_ACTION_1;
2563 if (door_state & DOOR_ACTION_2)
2564 door2 = door_state & DOOR_ACTION_2;
2566 return(door1 | door2);
2569 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2570 door_state &= ~DOOR_OPEN_1;
2571 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2572 door_state &= ~DOOR_CLOSE_1;
2573 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2574 door_state &= ~DOOR_OPEN_2;
2575 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2576 door_state &= ~DOOR_CLOSE_2;
2578 door_delay_value = (door_state & DOOR_ACTION_1 ? door_1.step_delay :
2581 if (setup.quick_doors)
2583 stepsize = 20; /* must be choosen to always draw last frame */
2584 door_delay_value = 0;
2587 StopSound(SND_DOOR_OPENING);
2588 StopSound(SND_DOOR_CLOSING);
2592 if (global.autoplay_leveldir)
2594 door_state |= DOOR_NO_DELAY;
2595 door_state &= ~DOOR_CLOSE_ALL;
2598 if (door_state & DOOR_ACTION)
2600 boolean door_1_done = !(door_state & DOOR_ACTION_1);
2601 boolean door_2_done = !(door_state & DOOR_ACTION_2);
2602 int start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2603 int end = (door_state & DOOR_ACTION_1 &&
2604 door_1.anim_mode == ANIM_VERTICAL ? DYSIZE : DXSIZE);
2607 if (!(door_state & DOOR_NO_DELAY) && !setup.quick_doors)
2609 /* opening door sound has priority over simultaneously closing door */
2610 if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
2611 PlaySoundStereo(SND_DOOR_OPENING, SOUND_MIDDLE);
2612 else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
2613 PlaySoundStereo(SND_DOOR_CLOSING, SOUND_MIDDLE);
2616 for (x = start; x <= end && !(door_1_done && door_2_done); x += stepsize)
2618 Bitmap *bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2619 GC gc = bitmap->stored_clip_gc;
2621 if (door_state & DOOR_ACTION_1)
2623 int a = MIN(x * door_1.step_offset, end);
2624 int i = (door_state & DOOR_OPEN_1 ? end - a : a);
2628 BlitBitmap(bitmap_db_door, drawto,
2629 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i / 2,
2630 DXSIZE, DYSIZE - i / 2, DX, DY);
2632 ClearRectangle(drawto, DX, DY + DYSIZE - i / 2, DXSIZE, i / 2);
2635 if (door_1.anim_mode == ANIM_HORIZONTAL && x <= DXSIZE)
2637 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
2638 int dst1_x = DX + DXSIZE - i, dst1_y = DY;
2639 int src2_x = DXSIZE - i, src2_y = DOOR_GFX_PAGEY1;
2640 int dst2_x = DX, dst2_y = DY;
2641 int width = i, height = DYSIZE;
2643 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2644 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2647 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2648 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2651 else if (door_1.anim_mode == ANIM_VERTICAL && x <= DYSIZE)
2653 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
2654 int dst1_x = DX, dst1_y = DY + DYSIZE - i;
2655 int src2_x = 0, src2_y = DOOR_GFX_PAGEY1 + DYSIZE - i;
2656 int dst2_x = DX, dst2_y = DY;
2657 int width = DXSIZE, height = i;
2659 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2660 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2663 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2664 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2667 else if (x <= DXSIZE) /* ANIM_DEFAULT */
2669 int j = (door_1.anim_mode == ANIM_DEFAULT ? (DXSIZE - i) / 3 : 0);
2671 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2672 BlitBitmapMasked(bitmap, drawto,
2673 DXSIZE, DOOR_GFX_PAGEY1, i, 77,
2674 DX + DXSIZE - i, DY + j);
2675 BlitBitmapMasked(bitmap, drawto,
2676 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
2677 DX + DXSIZE - i, DY + 140 + j);
2678 SetClipOrigin(bitmap, gc, DX - DXSIZE + i,
2679 DY - (DOOR_GFX_PAGEY1 + j));
2680 BlitBitmapMasked(bitmap, drawto,
2681 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
2683 BlitBitmapMasked(bitmap, drawto,
2684 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
2687 BlitBitmapMasked(bitmap, drawto,
2688 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2690 BlitBitmapMasked(bitmap, drawto,
2691 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2693 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2694 BlitBitmapMasked(bitmap, drawto,
2695 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2696 DX + DXSIZE - i, DY + 77 + j);
2697 BlitBitmapMasked(bitmap, drawto,
2698 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2699 DX + DXSIZE - i, DY + 203 + j);
2702 redraw_mask |= REDRAW_DOOR_1;
2703 door_1_done = (a == end);
2706 if (door_state & DOOR_ACTION_2)
2708 int a = MIN(x * door_2.step_offset, VXSIZE);
2709 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - a : a);
2713 BlitBitmap(bitmap_db_door, drawto,
2714 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i / 2,
2715 VXSIZE, VYSIZE - i / 2, VX, VY);
2717 ClearRectangle(drawto, VX, VY + VYSIZE - i / 2, VXSIZE, i / 2);
2720 if (door_2.anim_mode == ANIM_HORIZONTAL && x <= VXSIZE)
2722 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
2723 int dst1_x = VX + VXSIZE - i, dst1_y = VY;
2724 int src2_x = VXSIZE - i, src2_y = DOOR_GFX_PAGEY2;
2725 int dst2_x = VX, dst2_y = VY;
2726 int width = i, height = VYSIZE;
2728 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2729 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2732 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2733 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2736 else if (door_2.anim_mode == ANIM_VERTICAL && x <= VYSIZE)
2738 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
2739 int dst1_x = VX, dst1_y = VY + VYSIZE - i;
2740 int src2_x = 0, src2_y = DOOR_GFX_PAGEY2 + VYSIZE - i;
2741 int dst2_x = VX, dst2_y = VY;
2742 int width = VXSIZE, height = i;
2744 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2745 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2748 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2749 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2752 else if (x <= VXSIZE) /* ANIM_DEFAULT */
2754 int j = (door_2.anim_mode == ANIM_DEFAULT ? (VXSIZE - i) / 3 : 0);
2756 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2757 BlitBitmapMasked(bitmap, drawto,
2758 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
2759 VX + VXSIZE - i, VY + j);
2760 SetClipOrigin(bitmap, gc,
2761 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2762 BlitBitmapMasked(bitmap, drawto,
2763 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
2766 BlitBitmapMasked(bitmap, drawto,
2767 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2768 i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
2769 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2770 BlitBitmapMasked(bitmap, drawto,
2771 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2773 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2776 redraw_mask |= REDRAW_DOOR_2;
2777 door_2_done = (a == VXSIZE);
2782 if (game_status == GAME_MODE_MAIN)
2785 if (!(door_state & DOOR_NO_DELAY))
2786 WaitUntilDelayReached(&door_delay, door_delay_value);
2791 if (setup.quick_doors)
2793 StopSound(SND_DOOR_OPENING);
2794 StopSound(SND_DOOR_CLOSING);
2798 if (door_state & DOOR_ACTION_1)
2799 door1 = door_state & DOOR_ACTION_1;
2800 if (door_state & DOOR_ACTION_2)
2801 door2 = door_state & DOOR_ACTION_2;
2803 return (door1 | door2);
2806 void DrawSpecialEditorDoor()
2808 /* draw bigger toolbox window */
2809 BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
2810 DOOR_GFX_PAGEX7, 0, EXSIZE + 8, 8,
2812 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2813 EX - 4, VY - 4, EXSIZE + 8, EYSIZE - VYSIZE + 4,
2816 redraw_mask |= REDRAW_ALL;
2819 void UndrawSpecialEditorDoor()
2821 /* draw normal tape recorder window */
2822 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2823 EX - 4, EY - 12, EXSIZE + 8, EYSIZE - VYSIZE + 12,
2826 redraw_mask |= REDRAW_ALL;
2830 /* ---------- new tool button stuff ---------------------------------------- */
2832 /* graphic position values for tool buttons */
2833 #define TOOL_BUTTON_YES_XPOS 2
2834 #define TOOL_BUTTON_YES_YPOS 250
2835 #define TOOL_BUTTON_YES_GFX_YPOS 0
2836 #define TOOL_BUTTON_YES_XSIZE 46
2837 #define TOOL_BUTTON_YES_YSIZE 28
2838 #define TOOL_BUTTON_NO_XPOS 52
2839 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2840 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2841 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2842 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2843 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2844 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2845 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2846 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2847 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2848 #define TOOL_BUTTON_PLAYER_XSIZE 30
2849 #define TOOL_BUTTON_PLAYER_YSIZE 30
2850 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2851 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2852 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2853 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2854 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2855 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2856 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2857 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2858 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2859 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2860 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2861 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2862 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2863 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2864 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2865 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2866 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2867 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2868 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2869 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2878 } toolbutton_info[NUM_TOOL_BUTTONS] =
2881 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2882 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2883 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2888 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2889 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2890 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2895 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2896 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2897 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2898 TOOL_CTRL_ID_CONFIRM,
2902 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2903 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2904 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2905 TOOL_CTRL_ID_PLAYER_1,
2909 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2910 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2911 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2912 TOOL_CTRL_ID_PLAYER_2,
2916 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2917 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2918 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2919 TOOL_CTRL_ID_PLAYER_3,
2923 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2924 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2925 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2926 TOOL_CTRL_ID_PLAYER_4,
2931 void CreateToolButtons()
2935 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2937 Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2938 Bitmap *deco_bitmap = None;
2939 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2940 struct GadgetInfo *gi;
2941 unsigned long event_mask;
2942 int gd_xoffset, gd_yoffset;
2943 int gd_x1, gd_x2, gd_y;
2946 event_mask = GD_EVENT_RELEASED;
2948 gd_xoffset = toolbutton_info[i].xpos;
2949 gd_yoffset = toolbutton_info[i].ypos;
2950 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2951 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2952 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2954 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2956 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
2958 getMiniGraphicSource(PLAYER_NR_GFX(IMG_PLAYER_1, player_nr),
2959 &deco_bitmap, &deco_x, &deco_y);
2960 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2961 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2964 gi = CreateGadget(GDI_CUSTOM_ID, id,
2965 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2966 GDI_X, DX + toolbutton_info[i].x,
2967 GDI_Y, DY + toolbutton_info[i].y,
2968 GDI_WIDTH, toolbutton_info[i].width,
2969 GDI_HEIGHT, toolbutton_info[i].height,
2970 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2971 GDI_STATE, GD_BUTTON_UNPRESSED,
2972 GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
2973 GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
2974 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
2975 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2976 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2977 GDI_DECORATION_SHIFTING, 1, 1,
2978 GDI_EVENT_MASK, event_mask,
2979 GDI_CALLBACK_ACTION, HandleToolButtons,
2983 Error(ERR_EXIT, "cannot create gadget");
2985 tool_gadget[id] = gi;
2989 void FreeToolButtons()
2993 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2994 FreeGadget(tool_gadget[i]);
2997 static void UnmapToolButtons()
3001 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
3002 UnmapGadget(tool_gadget[i]);
3005 static void HandleToolButtons(struct GadgetInfo *gi)
3007 request_gadget_id = gi->custom_id;
3015 boolean is_rnd_to_em_mapping; /* unique mapping EM <-> RND */
3016 boolean is_backside; /* backside of moving element */
3022 mapping_EM_to_RND_list[] =
3025 Xblank, TRUE, FALSE,
3029 Yacid_splash_eB, FALSE, TRUE,
3030 EL_ACID_SPLASH_RIGHT, -1, -1
3033 Yacid_splash_wB, FALSE, TRUE,
3034 EL_ACID_SPLASH_LEFT, -1, -1
3037 #ifdef EM_ENGINE_BAD_ROLL
3039 Xstone_force_e, FALSE, FALSE,
3040 EL_ROCK, -1, MV_BIT_RIGHT
3043 Xstone_force_w, FALSE, FALSE,
3044 EL_ROCK, -1, MV_BIT_LEFT
3047 Xnut_force_e, FALSE, FALSE,
3048 EL_NUT, -1, MV_BIT_RIGHT
3051 Xnut_force_w, FALSE, FALSE,
3052 EL_NUT, -1, MV_BIT_LEFT
3055 Xspring_force_e, FALSE, FALSE,
3056 EL_SPRING, -1, MV_BIT_RIGHT
3059 Xspring_force_w, FALSE, FALSE,
3060 EL_SPRING, -1, MV_BIT_LEFT
3063 Xemerald_force_e, FALSE, FALSE,
3064 EL_EMERALD, -1, MV_BIT_RIGHT
3067 Xemerald_force_w, FALSE, FALSE,
3068 EL_EMERALD, -1, MV_BIT_LEFT
3071 Xdiamond_force_e, FALSE, FALSE,
3072 EL_DIAMOND, -1, MV_BIT_RIGHT
3075 Xdiamond_force_w, FALSE, FALSE,
3076 EL_DIAMOND, -1, MV_BIT_LEFT
3079 Xbomb_force_e, FALSE, FALSE,
3080 EL_BOMB, -1, MV_BIT_RIGHT
3083 Xbomb_force_w, FALSE, FALSE,
3084 EL_BOMB, -1, MV_BIT_LEFT
3086 #endif /* EM_ENGINE_BAD_ROLL */
3089 Xstone, TRUE, FALSE,
3093 Xstone_pause, FALSE, FALSE,
3097 Xstone_fall, FALSE, FALSE,
3101 Ystone_s, FALSE, FALSE,
3102 EL_ROCK, ACTION_FALLING, -1
3105 Ystone_sB, FALSE, TRUE,
3106 EL_ROCK, ACTION_FALLING, -1
3109 Ystone_e, FALSE, FALSE,
3110 EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT
3113 Ystone_eB, FALSE, TRUE,
3114 EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT
3117 Ystone_w, FALSE, FALSE,
3118 EL_ROCK, ACTION_MOVING, MV_BIT_LEFT
3121 Ystone_wB, FALSE, TRUE,
3122 EL_ROCK, ACTION_MOVING, MV_BIT_LEFT
3129 Xnut_pause, FALSE, FALSE,
3133 Xnut_fall, FALSE, FALSE,
3137 Ynut_s, FALSE, FALSE,
3138 EL_NUT, ACTION_FALLING, -1
3141 Ynut_sB, FALSE, TRUE,
3142 EL_NUT, ACTION_FALLING, -1
3145 Ynut_e, FALSE, FALSE,
3146 EL_NUT, ACTION_MOVING, MV_BIT_RIGHT
3149 Ynut_eB, FALSE, TRUE,
3150 EL_NUT, ACTION_MOVING, MV_BIT_RIGHT
3153 Ynut_w, FALSE, FALSE,
3154 EL_NUT, ACTION_MOVING, MV_BIT_LEFT
3157 Ynut_wB, FALSE, TRUE,
3158 EL_NUT, ACTION_MOVING, MV_BIT_LEFT
3161 Xbug_n, TRUE, FALSE,
3165 Xbug_e, TRUE, FALSE,
3166 EL_BUG_RIGHT, -1, -1
3169 Xbug_s, TRUE, FALSE,
3173 Xbug_w, TRUE, FALSE,
3177 Xbug_gon, FALSE, FALSE,
3181 Xbug_goe, FALSE, FALSE,
3182 EL_BUG_RIGHT, -1, -1
3185 Xbug_gos, FALSE, FALSE,
3189 Xbug_gow, FALSE, FALSE,
3193 Ybug_n, FALSE, FALSE,
3194 EL_BUG, ACTION_MOVING, MV_BIT_UP
3197 Ybug_nB, FALSE, TRUE,
3198 EL_BUG, ACTION_MOVING, MV_BIT_UP
3201 Ybug_e, FALSE, FALSE,
3202 EL_BUG, ACTION_MOVING, MV_BIT_RIGHT
3205 Ybug_eB, FALSE, TRUE,
3206 EL_BUG, ACTION_MOVING, MV_BIT_RIGHT
3209 Ybug_s, FALSE, FALSE,
3210 EL_BUG, ACTION_MOVING, MV_BIT_DOWN
3213 Ybug_sB, FALSE, TRUE,
3214 EL_BUG, ACTION_MOVING, MV_BIT_DOWN
3217 Ybug_w, FALSE, FALSE,
3218 EL_BUG, ACTION_MOVING, MV_BIT_LEFT
3221 Ybug_wB, FALSE, TRUE,
3222 EL_BUG, ACTION_MOVING, MV_BIT_LEFT
3225 Ybug_w_n, FALSE, FALSE,
3226 EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_UP
3229 Ybug_n_e, FALSE, FALSE,
3230 EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3233 Ybug_e_s, FALSE, FALSE,
3234 EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
3237 Ybug_s_w, FALSE, FALSE,
3238 EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3241 Ybug_e_n, FALSE, FALSE,
3242 EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
3245 Ybug_s_e, FALSE, FALSE,
3246 EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3249 Ybug_w_s, FALSE, FALSE,
3250 EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
3253 Ybug_n_w, FALSE, FALSE,
3254 EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3257 Ybug_stone, FALSE, FALSE,
3258 EL_BUG, ACTION_SMASHED_BY_ROCK, -1
3261 Ybug_spring, FALSE, FALSE,
3262 EL_BUG, ACTION_SMASHED_BY_SPRING, -1
3265 Xtank_n, TRUE, FALSE,
3266 EL_SPACESHIP_UP, -1, -1
3269 Xtank_e, TRUE, FALSE,
3270 EL_SPACESHIP_RIGHT, -1, -1
3273 Xtank_s, TRUE, FALSE,
3274 EL_SPACESHIP_DOWN, -1, -1
3277 Xtank_w, TRUE, FALSE,
3278 EL_SPACESHIP_LEFT, -1, -1
3281 Xtank_gon, FALSE, FALSE,
3282 EL_SPACESHIP_UP, -1, -1
3285 Xtank_goe, FALSE, FALSE,
3286 EL_SPACESHIP_RIGHT, -1, -1
3289 Xtank_gos, FALSE, FALSE,
3290 EL_SPACESHIP_DOWN, -1, -1
3293 Xtank_gow, FALSE, FALSE,
3294 EL_SPACESHIP_LEFT, -1, -1
3297 Ytank_n, FALSE, FALSE,
3298 EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP
3301 Ytank_nB, FALSE, TRUE,
3302 EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP
3305 Ytank_e, FALSE, FALSE,
3306 EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT
3309 Ytank_eB, FALSE, TRUE,
3310 EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT
3313 Ytank_s, FALSE, FALSE,
3314 EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN
3317 Ytank_sB, FALSE, TRUE,
3318 EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN
3321 Ytank_w, FALSE, FALSE,
3322 EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT
3325 Ytank_wB, FALSE, TRUE,
3326 EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT
3329 Ytank_w_n, FALSE, FALSE,
3330 EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_UP
3333 Ytank_n_e, FALSE, FALSE,
3334 EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3337 Ytank_e_s, FALSE, FALSE,
3338 EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
3341 Ytank_s_w, FALSE, FALSE,
3342 EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3345 Ytank_e_n, FALSE, FALSE,
3346 EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
3349 Ytank_s_e, FALSE, FALSE,
3350 EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3353 Ytank_w_s, FALSE, FALSE,
3354 EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
3357 Ytank_n_w, FALSE, FALSE,
3358 EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3361 Ytank_stone, FALSE, FALSE,
3362 EL_SPACESHIP, ACTION_SMASHED_BY_ROCK, -1
3365 Ytank_spring, FALSE, FALSE,
3366 EL_SPACESHIP, ACTION_SMASHED_BY_SPRING, -1
3369 Xandroid, TRUE, FALSE,
3370 EL_EMC_ANDROID, ACTION_ACTIVE, -1
3373 Xandroid_1_n, FALSE, FALSE,
3374 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_UP
3377 Xandroid_2_n, FALSE, FALSE,
3378 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_UP
3381 Xandroid_1_e, FALSE, FALSE,
3382 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_RIGHT
3385 Xandroid_2_e, FALSE, FALSE,
3386 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_RIGHT
3389 Xandroid_1_w, FALSE, FALSE,
3390 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_LEFT
3393 Xandroid_2_w, FALSE, FALSE,
3394 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_LEFT
3397 Xandroid_1_s, FALSE, FALSE,
3398 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_DOWN
3401 Xandroid_2_s, FALSE, FALSE,
3402 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_DOWN
3405 Yandroid_n, FALSE, FALSE,
3406 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_UP
3409 Yandroid_nB, FALSE, TRUE,
3410 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_UP
3413 Yandroid_ne, FALSE, FALSE,
3414 EL_EMC_ANDROID, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3417 Yandroid_neB, FALSE, TRUE,
3418 EL_EMC_ANDROID, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3421 Yandroid_e, FALSE, FALSE,
3422 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_RIGHT
3425 Yandroid_eB, FALSE, TRUE,
3426 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_RIGHT
3429 Yandroid_se, FALSE, FALSE,
3430 EL_EMC_ANDROID, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3433 Yandroid_seB, FALSE, TRUE,
3434 EL_EMC_ANDROID, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3437 Yandroid_s, FALSE, FALSE,
3438 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_DOWN
3441 Yandroid_sB, FALSE, TRUE,
3442 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_DOWN
3445 Yandroid_sw, FALSE, FALSE,
3446 EL_EMC_ANDROID, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3449 Yandroid_swB, FALSE, TRUE,
3450 EL_EMC_ANDROID, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3453 Yandroid_w, FALSE, FALSE,
3454 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_LEFT
3457 Yandroid_wB, FALSE, TRUE,
3458 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_LEFT
3461 Yandroid_nw, FALSE, FALSE,
3462 EL_EMC_ANDROID, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3465 Yandroid_nwB, FALSE, TRUE,
3466 EL_EMC_ANDROID, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3469 Xspring, TRUE, FALSE,
3473 Xspring_pause, FALSE, FALSE,
3477 Xspring_e, FALSE, FALSE,
3481 Xspring_w, FALSE, FALSE,
3485 Xspring_fall, FALSE, FALSE,
3489 Yspring_s, FALSE, FALSE,
3490 EL_SPRING, ACTION_FALLING, -1
3493 Yspring_sB, FALSE, TRUE,
3494 EL_SPRING, ACTION_FALLING, -1
3497 Yspring_e, FALSE, FALSE,
3498 EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT
3501 Yspring_eB, FALSE, TRUE,
3502 EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT
3505 Yspring_w, FALSE, FALSE,
3506 EL_SPRING, ACTION_MOVING, MV_BIT_LEFT
3509 Yspring_wB, FALSE, TRUE,
3510 EL_SPRING, ACTION_MOVING, MV_BIT_LEFT
3513 Yspring_kill_e, FALSE, FALSE,
3514 EL_ROBOT, ACTION_SLURPED_BY_SPRING, MV_BIT_RIGHT
3517 Yspring_kill_eB, FALSE, TRUE,
3518 EL_ROBOT, ACTION_SLURPED_BY_SPRING, MV_BIT_RIGHT
3521 Yspring_kill_w, FALSE, FALSE,
3522 EL_ROBOT, ACTION_SLURPED_BY_SPRING, MV_BIT_LEFT
3525 Yspring_kill_wB, FALSE, TRUE,
3526 EL_ROBOT, ACTION_SLURPED_BY_SPRING, MV_BIT_LEFT
3529 Xeater_n, TRUE, FALSE,
3533 Xeater_e, FALSE, FALSE,
3537 Xeater_w, FALSE, FALSE,
3541 Xeater_s, FALSE, FALSE,
3545 Yeater_n, FALSE, FALSE,
3546 EL_YAMYAM, ACTION_MOVING, MV_BIT_UP
3549 Yeater_nB, FALSE, TRUE,
3550 EL_YAMYAM, ACTION_MOVING, MV_BIT_UP
3553 Yeater_e, FALSE, FALSE,
3554 EL_YAMYAM, ACTION_MOVING, MV_BIT_RIGHT
3557 Yeater_eB, FALSE, TRUE,
3558 EL_YAMYAM, ACTION_MOVING, MV_BIT_RIGHT
3561 Yeater_s, FALSE, FALSE,
3562 EL_YAMYAM, ACTION_MOVING, MV_BIT_DOWN
3565 Yeater_sB, FALSE, TRUE,
3566 EL_YAMYAM, ACTION_MOVING, MV_BIT_DOWN
3569 Yeater_w, FALSE, FALSE,
3570 EL_YAMYAM, ACTION_MOVING, MV_BIT_LEFT
3573 Yeater_wB, FALSE, TRUE,
3574 EL_YAMYAM, ACTION_MOVING, MV_BIT_LEFT
3577 Yeater_stone, FALSE, FALSE,
3578 EL_YAMYAM, ACTION_SMASHED_BY_ROCK, -1
3581 Yeater_spring, FALSE, FALSE,
3582 EL_YAMYAM, ACTION_SMASHED_BY_SPRING, -1
3585 Xalien, TRUE, FALSE,
3589 Xalien_pause, FALSE, FALSE,
3593 Yalien_n, FALSE, FALSE,
3594 EL_ROBOT, ACTION_MOVING, MV_BIT_UP
3597 Yalien_nB, FALSE, TRUE,
3598 EL_ROBOT, ACTION_MOVING, MV_BIT_UP
3601 Yalien_e, FALSE, FALSE,
3602 EL_ROBOT, ACTION_MOVING, MV_BIT_RIGHT
3605 Yalien_eB, FALSE, TRUE,
3606 EL_ROBOT, ACTION_MOVING, MV_BIT_RIGHT
3609 Yalien_s, FALSE, FALSE,
3610 EL_ROBOT, ACTION_MOVING, MV_BIT_DOWN
3613 Yalien_sB, FALSE, TRUE,
3614 EL_ROBOT, ACTION_MOVING, MV_BIT_DOWN
3617 Yalien_w, FALSE, FALSE,
3618 EL_ROBOT, ACTION_MOVING, MV_BIT_LEFT
3621 Yalien_wB, FALSE, TRUE,
3622 EL_ROBOT, ACTION_MOVING, MV_BIT_LEFT
3625 Yalien_stone, FALSE, FALSE,
3626 EL_ROBOT, ACTION_SMASHED_BY_ROCK, -1
3629 Yalien_spring, FALSE, FALSE,
3630 EL_ROBOT, ACTION_SMASHED_BY_SPRING, -1
3633 Xemerald, TRUE, FALSE,
3637 Xemerald_pause, FALSE, FALSE,
3641 Xemerald_fall, FALSE, FALSE,
3645 Xemerald_shine, FALSE, FALSE,
3646 EL_EMERALD, ACTION_TWINKLING, -1
3649 Yemerald_s, FALSE, FALSE,
3650 EL_EMERALD, ACTION_FALLING, -1
3653 Yemerald_sB, FALSE, TRUE,
3654 EL_EMERALD, ACTION_FALLING, -1
3657 Yemerald_e, FALSE, FALSE,
3658 EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT
3661 Yemerald_eB, FALSE, TRUE,
3662 EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT
3665 Yemerald_w, FALSE, FALSE,
3666 EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT
3669 Yemerald_wB, FALSE, TRUE,
3670 EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT
3673 Yemerald_eat, FALSE, FALSE,
3674 EL_EMERALD, ACTION_COLLECTING, -1
3677 Yemerald_stone, FALSE, FALSE,
3678 EL_NUT, ACTION_BREAKING, -1
3681 Xdiamond, TRUE, FALSE,
3685 Xdiamond_pause, FALSE, FALSE,
3689 Xdiamond_fall, FALSE, FALSE,
3693 Xdiamond_shine, FALSE, FALSE,
3694 EL_DIAMOND, ACTION_TWINKLING, -1
3697 Ydiamond_s, FALSE, FALSE,
3698 EL_DIAMOND, ACTION_FALLING, -1
3701 Ydiamond_sB, FALSE, TRUE,
3702 EL_DIAMOND, ACTION_FALLING, -1
3705 Ydiamond_e, FALSE, FALSE,
3706 EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT
3709 Ydiamond_eB, FALSE, TRUE,
3710 EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT
3713 Ydiamond_w, FALSE, FALSE,
3714 EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT
3717 Ydiamond_wB, FALSE, TRUE,
3718 EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT
3721 Ydiamond_eat, FALSE, FALSE,
3722 EL_DIAMOND, ACTION_COLLECTING, -1
3725 Ydiamond_stone, FALSE, FALSE,
3726 EL_DIAMOND, ACTION_SMASHED_BY_ROCK, -1
3729 Xdrip_fall, TRUE, FALSE,
3730 EL_AMOEBA_DROP, -1, -1
3733 Xdrip_stretch, FALSE, FALSE,
3734 EL_AMOEBA_DROP, ACTION_FALLING, -1
3737 Xdrip_stretchB, FALSE, TRUE,
3738 EL_AMOEBA_DROP, ACTION_FALLING, -1
3741 Xdrip_eat, FALSE, FALSE,
3742 EL_AMOEBA_DROP, ACTION_GROWING, -1
3745 Ydrip_s1, FALSE, FALSE,
3746 EL_AMOEBA_DROP, ACTION_FALLING, -1
3749 Ydrip_s1B, FALSE, TRUE,
3750 EL_AMOEBA_DROP, ACTION_FALLING, -1
3753 Ydrip_s2, FALSE, FALSE,
3754 EL_AMOEBA_DROP, ACTION_FALLING, -1
3757 Ydrip_s2B, FALSE, TRUE,
3758 EL_AMOEBA_DROP, ACTION_FALLING, -1
3765 Xbomb_pause, FALSE, FALSE,
3769 Xbomb_fall, FALSE, FALSE,
3773 Ybomb_s, FALSE, FALSE,
3774 EL_BOMB, ACTION_FALLING, -1
3777 Ybomb_sB, FALSE, TRUE,
3778 EL_BOMB, ACTION_FALLING, -1
3781 Ybomb_e, FALSE, FALSE,
3782 EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT
3785 Ybomb_eB, FALSE, TRUE,
3786 EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT
3789 Ybomb_w, FALSE, FALSE,
3790 EL_BOMB, ACTION_MOVING, MV_BIT_LEFT
3793 Ybomb_wB, FALSE, TRUE,
3794 EL_BOMB, ACTION_MOVING, MV_BIT_LEFT
3797 Ybomb_eat, FALSE, FALSE,
3798 EL_BOMB, ACTION_SMASHED_BY_ROCK, -1
3801 Xballoon, TRUE, FALSE,
3805 Yballoon_n, FALSE, FALSE,
3806 EL_BALLOON, ACTION_MOVING, MV_BIT_UP
3809 Yballoon_nB, FALSE, TRUE,
3810 EL_BALLOON, ACTION_MOVING, MV_BIT_UP
3813 Yballoon_e, FALSE, FALSE,
3814 EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT
3817 Yballoon_eB, FALSE, TRUE,
3818 EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT
3821 Yballoon_s, FALSE, FALSE,
3822 EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN
3825 Yballoon_sB, FALSE, TRUE,
3826 EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN
3829 Yballoon_w, FALSE, FALSE,
3830 EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT
3833 Yballoon_wB, FALSE, TRUE,
3834 EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT
3837 Xgrass, TRUE, FALSE,
3838 EL_EMC_GRASS, -1, -1
3841 Ygrass_nB, FALSE, TRUE,
3842 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_UP
3845 Ygrass_eB, FALSE, TRUE,
3846 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_RIGHT
3849 Ygrass_sB, FALSE, TRUE,
3850 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_DOWN
3853 Ygrass_wB, FALSE, TRUE,
3854 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_LEFT
3861 Ydirt_nB, FALSE, TRUE,
3862 EL_SAND, ACTION_DIGGING, MV_BIT_UP
3865 Ydirt_eB, FALSE, TRUE,
3866 EL_SAND, ACTION_DIGGING, MV_BIT_RIGHT
3869 Ydirt_sB, FALSE, TRUE,
3870 EL_SAND, ACTION_DIGGING, MV_BIT_DOWN
3873 Ydirt_wB, FALSE, TRUE,
3874 EL_SAND, ACTION_DIGGING, MV_BIT_LEFT
3877 Xacid_ne, TRUE, FALSE,
3878 EL_ACID_POOL_TOPRIGHT, -1, -1
3881 Xacid_se, TRUE, FALSE,
3882 EL_ACID_POOL_BOTTOMRIGHT, -1, -1
3885 Xacid_s, TRUE, FALSE,
3886 EL_ACID_POOL_BOTTOM, -1, -1
3889 Xacid_sw, TRUE, FALSE,
3890 EL_ACID_POOL_BOTTOMLEFT, -1, -1
3893 Xacid_nw, TRUE, FALSE,
3894 EL_ACID_POOL_TOPLEFT, -1, -1
3897 Xacid_1, TRUE, FALSE,
3901 Xacid_2, FALSE, FALSE,
3905 Xacid_3, FALSE, FALSE,
3909 Xacid_4, FALSE, FALSE,
3913 Xacid_5, FALSE, FALSE,
3917 Xacid_6, FALSE, FALSE,
3921 Xacid_7, FALSE, FALSE,
3925 Xacid_8, FALSE, FALSE,
3929 Xball_1, TRUE, FALSE,
3930 EL_EMC_MAGIC_BALL, -1, -1
3933 Xball_1B, FALSE, TRUE,
3934 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
3937 Xball_2, FALSE, FALSE,
3938 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
3941 Xball_2B, FALSE, TRUE,
3942 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
3945 Yball_eat, FALSE, FALSE,
3946 EL_EMC_MAGIC_BALL, ACTION_DROPPING, -1
3949 Xgrow_ns, TRUE, FALSE,
3950 EL_EXPANDABLE_WALL_VERTICAL, -1, -1
3953 Ygrow_ns_eat, FALSE, FALSE,
3954 EL_EXPANDABLE_WALL_VERTICAL, ACTION_GROWING, -1
3957 Xgrow_ew, TRUE, FALSE,
3958 EL_EXPANDABLE_WALL_HORIZONTAL, -1, -1
3961 Ygrow_ew_eat, FALSE, FALSE,
3962 EL_EXPANDABLE_WALL_HORIZONTAL, ACTION_GROWING, -1
3965 Xwonderwall, TRUE, FALSE,
3966 EL_MAGIC_WALL, -1, -1
3969 XwonderwallB, FALSE, FALSE,
3970 EL_MAGIC_WALL, ACTION_ACTIVE, -1
3973 Xamoeba_1, TRUE, FALSE,
3974 EL_AMOEBA_DRY, ACTION_OTHER, -1
3977 Xamoeba_2, FALSE, FALSE,
3978 EL_AMOEBA_DRY, ACTION_OTHER, -1
3981 Xamoeba_3, FALSE, FALSE,
3982 EL_AMOEBA_DRY, ACTION_OTHER, -1
3985 Xamoeba_4, FALSE, FALSE,
3986 EL_AMOEBA_DRY, ACTION_OTHER, -1
3989 Xamoeba_5, FALSE, FALSE,
3990 EL_AMOEBA_WET, ACTION_OTHER, -1
3993 Xamoeba_6, FALSE, FALSE,
3994 EL_AMOEBA_WET, ACTION_OTHER, -1
3997 Xamoeba_7, FALSE, FALSE,
3998 EL_AMOEBA_WET, ACTION_OTHER, -1
4001 Xamoeba_8, FALSE, FALSE,
4002 EL_AMOEBA_WET, ACTION_OTHER, -1
4005 Xdoor_1, TRUE, FALSE,
4006 EL_EM_GATE_1, -1, -1
4009 Xdoor_2, TRUE, FALSE,
4010 EL_EM_GATE_2, -1, -1
4013 Xdoor_3, TRUE, FALSE,
4014 EL_EM_GATE_3, -1, -1
4017 Xdoor_4, TRUE, FALSE,
4018 EL_EM_GATE_4, -1, -1
4021 Xdoor_5, TRUE, FALSE,
4022 EL_EM_GATE_5, -1, -1
4025 Xdoor_6, TRUE, FALSE,
4026 EL_EM_GATE_6, -1, -1
4029 Xdoor_7, TRUE, FALSE,
4030 EL_EM_GATE_7, -1, -1
4033 Xdoor_8, TRUE, FALSE,
4034 EL_EM_GATE_8, -1, -1
4037 Xkey_1, TRUE, FALSE,
4041 Xkey_2, TRUE, FALSE,
4045 Xkey_3, TRUE, FALSE,
4049 Xkey_4, TRUE, FALSE,
4053 Xkey_5, TRUE, FALSE,
4057 Xkey_6, TRUE, FALSE,
4061 Xkey_7, TRUE, FALSE,
4065 Xkey_8, TRUE, FALSE,
4069 Xwind_n, TRUE, FALSE,
4070 EL_BALLOON_SWITCH_UP, -1, -1
4073 Xwind_e, TRUE, FALSE,
4074 EL_BALLOON_SWITCH_RIGHT, -1, -1
4077 Xwind_s, TRUE, FALSE,
4078 EL_BALLOON_SWITCH_DOWN, -1, -1
4081 Xwind_w, TRUE, FALSE,
4082 EL_BALLOON_SWITCH_LEFT, -1, -1
4085 Xwind_nesw, TRUE, FALSE,
4086 EL_BALLOON_SWITCH_ANY, -1, -1
4089 Xwind_stop, TRUE, FALSE,
4090 EL_BALLOON_SWITCH_NONE, -1, -1
4094 EL_EXIT_CLOSED, -1, -1
4097 Xexit_1, TRUE, FALSE,
4098 EL_EXIT_OPEN, -1, -1
4101 Xexit_2, FALSE, FALSE,
4102 EL_EXIT_OPEN, -1, -1
4105 Xexit_3, FALSE, FALSE,
4106 EL_EXIT_OPEN, -1, -1
4109 Xdynamite, TRUE, FALSE,
4113 Ydynamite_eat, FALSE, FALSE,
4114 EL_DYNAMITE, ACTION_COLLECTING, -1
4117 Xdynamite_1, TRUE, FALSE,
4118 EL_DYNAMITE_ACTIVE, -1, -1
4121 Xdynamite_2, FALSE, FALSE,
4122 EL_DYNAMITE_ACTIVE, -1, -1
4125 Xdynamite_3, FALSE, FALSE,
4126 EL_DYNAMITE_ACTIVE, -1, -1
4129 Xdynamite_4, FALSE, FALSE,
4130 EL_DYNAMITE_ACTIVE, -1, -1
4133 Xbumper, TRUE, FALSE,
4134 EL_EMC_SPRING_BUMPER, -1, -1
4137 XbumperB, FALSE, FALSE,
4138 EL_EMC_SPRING_BUMPER, ACTION_ACTIVE, -1
4141 Xwheel, TRUE, FALSE,
4142 EL_ROBOT_WHEEL, -1, -1
4145 XwheelB, FALSE, FALSE,
4146 EL_ROBOT_WHEEL, ACTION_ACTIVE, -1
4149 Xswitch, TRUE, FALSE,
4150 EL_EMC_MAGIC_BALL_SWITCH, -1, -1
4153 XswitchB, FALSE, FALSE,
4154 EL_EMC_MAGIC_BALL_SWITCH, ACTION_ACTIVE, -1
4158 EL_QUICKSAND_EMPTY, -1, -1
4161 Xsand_stone, TRUE, FALSE,
4162 EL_QUICKSAND_FULL, -1, -1
4165 Xsand_stonein_1, FALSE, FALSE,
4166 EL_ROCK, ACTION_FILLING, -1
4169 Xsand_stonein_2, FALSE, FALSE,
4170 EL_ROCK, ACTION_FILLING, -1
4173 Xsand_stonein_3, FALSE, FALSE,
4174 EL_ROCK, ACTION_FILLING, -1
4177 Xsand_stonein_4, FALSE, FALSE,
4178 EL_ROCK, ACTION_FILLING, -1
4181 Xsand_stonesand_1, FALSE, FALSE,
4182 EL_QUICKSAND_FULL, -1, -1
4185 Xsand_stonesand_2, FALSE, FALSE,
4186 EL_QUICKSAND_FULL, -1, -1
4189 Xsand_stonesand_3, FALSE, FALSE,
4190 EL_QUICKSAND_FULL, -1, -1
4193 Xsand_stonesand_4, FALSE, FALSE,
4194 EL_QUICKSAND_FULL, -1, -1
4197 Xsand_stoneout_1, FALSE, FALSE,
4198 EL_ROCK, ACTION_EMPTYING, -1
4201 Xsand_stoneout_2, FALSE, FALSE,
4202 EL_ROCK, ACTION_EMPTYING, -1
4205 Xsand_sandstone_1, FALSE, FALSE,
4206 EL_QUICKSAND_FULL, -1, -1
4209 Xsand_sandstone_2, FALSE, FALSE,
4210 EL_QUICKSAND_FULL, -1, -1
4213 Xsand_sandstone_3, FALSE, FALSE,
4214 EL_QUICKSAND_FULL, -1, -1
4217 Xsand_sandstone_4, FALSE, FALSE,
4218 EL_QUICKSAND_FULL, -1, -1
4221 Xplant, TRUE, FALSE,
4222 EL_EMC_PLANT, -1, -1
4225 Yplant, FALSE, FALSE,
4226 EL_EMC_PLANT, -1, -1
4229 Xlenses, TRUE, FALSE,
4230 EL_EMC_LENSES, -1, -1
4233 Xmagnify, TRUE, FALSE,
4234 EL_EMC_MAGNIFIER, -1, -1
4237 Xdripper, TRUE, FALSE,
4238 EL_EMC_DRIPPER, -1, -1
4241 XdripperB, FALSE, FALSE,
4242 EL_EMC_DRIPPER, ACTION_ACTIVE, -1
4245 Xfake_blank, TRUE, FALSE,
4246 EL_INVISIBLE_WALL, -1, -1
4249 Xfake_blankB, FALSE, FALSE,
4250 EL_INVISIBLE_WALL, ACTION_ACTIVE, -1
4253 Xfake_grass, TRUE, FALSE,
4254 EL_EMC_FAKE_GRASS, -1, -1
4257 Xfake_grassB, FALSE, FALSE,
4258 EL_EMC_FAKE_GRASS, ACTION_ACTIVE, -1
4261 Xfake_door_1, TRUE, FALSE,
4262 EL_EM_GATE_1_GRAY, -1, -1
4265 Xfake_door_2, TRUE, FALSE,
4266 EL_EM_GATE_2_GRAY, -1, -1
4269 Xfake_door_3, TRUE, FALSE,
4270 EL_EM_GATE_3_GRAY, -1, -1
4273 Xfake_door_4, TRUE, FALSE,
4274 EL_EM_GATE_4_GRAY, -1, -1
4277 Xfake_door_5, TRUE, FALSE,
4278 EL_EM_GATE_5_GRAY, -1, -1
4281 Xfake_door_6, TRUE, FALSE,
4282 EL_EM_GATE_6_GRAY, -1, -1
4285 Xfake_door_7, TRUE, FALSE,
4286 EL_EM_GATE_7_GRAY, -1, -1
4289 Xfake_door_8, TRUE, FALSE,
4290 EL_EM_GATE_8_GRAY, -1, -1
4293 Xsteel_1, TRUE, FALSE,
4294 EL_STEELWALL, -1, -1
4297 Xsteel_2, TRUE, FALSE,
4298 EL_EMC_STEELWALL_2, -1, -1
4301 Xsteel_3, TRUE, FALSE,
4302 EL_EMC_STEELWALL_3, -1, -1
4305 Xsteel_4, TRUE, FALSE,
4306 EL_EMC_STEELWALL_4, -1, -1
4309 Xwall_1, TRUE, FALSE,
4313 Xwall_2, TRUE, FALSE,
4314 EL_EMC_WALL_14, -1, -1
4317 Xwall_3, TRUE, FALSE,
4318 EL_EMC_WALL_15, -1, -1
4321 Xwall_4, TRUE, FALSE,
4322 EL_EMC_WALL_16, -1, -1
4325 Xround_wall_1, TRUE, FALSE,
4326 EL_WALL_SLIPPERY, -1, -1
4329 Xround_wall_2, TRUE, FALSE,
4330 EL_EMC_WALL_SLIPPERY_2, -1, -1
4333 Xround_wall_3, TRUE, FALSE,
4334 EL_EMC_WALL_SLIPPERY_3, -1, -1
4337 Xround_wall_4, TRUE, FALSE,
4338 EL_EMC_WALL_SLIPPERY_4, -1, -1
4341 Xdecor_1, TRUE, FALSE,
4342 EL_EMC_WALL_8, -1, -1
4345 Xdecor_2, TRUE, FALSE,
4346 EL_EMC_WALL_6, -1, -1
4349 Xdecor_3, TRUE, FALSE,
4350 EL_EMC_WALL_4, -1, -1
4353 Xdecor_4, TRUE, FALSE,
4354 EL_EMC_WALL_7, -1, -1
4357 Xdecor_5, TRUE, FALSE,
4358 EL_EMC_WALL_5, -1, -1
4361 Xdecor_6, TRUE, FALSE,
4362 EL_EMC_WALL_9, -1, -1
4365 Xdecor_7, TRUE, FALSE,
4366 EL_EMC_WALL_10, -1, -1
4369 Xdecor_8, TRUE, FALSE,
4370 EL_EMC_WALL_1, -1, -1
4373 Xdecor_9, TRUE, FALSE,
4374 EL_EMC_WALL_2, -1, -1
4377 Xdecor_10, TRUE, FALSE,
4378 EL_EMC_WALL_3, -1, -1
4381 Xdecor_11, TRUE, FALSE,
4382 EL_EMC_WALL_11, -1, -1
4385 Xdecor_12, TRUE, FALSE,
4386 EL_EMC_WALL_12, -1, -1
4389 Xalpha_0, TRUE, FALSE,
4390 EL_CHAR('0'), -1, -1
4393 Xalpha_1, TRUE, FALSE,
4394 EL_CHAR('1'), -1, -1
4397 Xalpha_2, TRUE, FALSE,
4398 EL_CHAR('2'), -1, -1
4401 Xalpha_3, TRUE, FALSE,
4402 EL_CHAR('3'), -1, -1
4405 Xalpha_4, TRUE, FALSE,
4406 EL_CHAR('4'), -1, -1
4409 Xalpha_5, TRUE, FALSE,
4410 EL_CHAR('5'), -1, -1
4413 Xalpha_6, TRUE, FALSE,
4414 EL_CHAR('6'), -1, -1
4417 Xalpha_7, TRUE, FALSE,
4418 EL_CHAR('7'), -1, -1
4421 Xalpha_8, TRUE, FALSE,
4422 EL_CHAR('8'), -1, -1
4425 Xalpha_9, TRUE, FALSE,
4426 EL_CHAR('9'), -1, -1
4429 Xalpha_excla, TRUE, FALSE,
4430 EL_CHAR('!'), -1, -1
4433 Xalpha_quote, TRUE, FALSE,
4434 EL_CHAR('"'), -1, -1
4437 Xalpha_comma, TRUE, FALSE,
4438 EL_CHAR(','), -1, -1
4441 Xalpha_minus, TRUE, FALSE,
4442 EL_CHAR('-'), -1, -1
4445 Xalpha_perio, TRUE, FALSE,
4446 EL_CHAR('.'), -1, -1
4449 Xalpha_colon, TRUE, FALSE,
4450 EL_CHAR(':'), -1, -1
4453 Xalpha_quest, TRUE, FALSE,
4454 EL_CHAR('?'), -1, -1
4457 Xalpha_a, TRUE, FALSE,
4458 EL_CHAR('A'), -1, -1
4461 Xalpha_b, TRUE, FALSE,
4462 EL_CHAR('B'), -1, -1
4465 Xalpha_c, TRUE, FALSE,
4466 EL_CHAR('C'), -1, -1
4469 Xalpha_d, TRUE, FALSE,
4470 EL_CHAR('D'), -1, -1
4473 Xalpha_e, TRUE, FALSE,
4474 EL_CHAR('E'), -1, -1
4477 Xalpha_f, TRUE, FALSE,
4478 EL_CHAR('F'), -1, -1
4481 Xalpha_g, TRUE, FALSE,
4482 EL_CHAR('G'), -1, -1
4485 Xalpha_h, TRUE, FALSE,
4486 EL_CHAR('H'), -1, -1
4489 Xalpha_i, TRUE, FALSE,
4490 EL_CHAR('I'), -1, -1
4493 Xalpha_j, TRUE, FALSE,
4494 EL_CHAR('J'), -1, -1
4497 Xalpha_k, TRUE, FALSE,
4498 EL_CHAR('K'), -1, -1
4501 Xalpha_l, TRUE, FALSE,
4502 EL_CHAR('L'), -1, -1
4505 Xalpha_m, TRUE, FALSE,
4506 EL_CHAR('M'), -1, -1
4509 Xalpha_n, TRUE, FALSE,
4510 EL_CHAR('N'), -1, -1
4513 Xalpha_o, TRUE, FALSE,
4514 EL_CHAR('O'), -1, -1
4517 Xalpha_p, TRUE, FALSE,
4518 EL_CHAR('P'), -1, -1
4521 Xalpha_q, TRUE, FALSE,
4522 EL_CHAR('Q'), -1, -1
4525 Xalpha_r, TRUE, FALSE,
4526 EL_CHAR('R'), -1, -1
4529 Xalpha_s, TRUE, FALSE,
4530 EL_CHAR('S'), -1, -1
4533 Xalpha_t, TRUE, FALSE,
4534 EL_CHAR('T'), -1, -1
4537 Xalpha_u, TRUE, FALSE,
4538 EL_CHAR('U'), -1, -1
4541 Xalpha_v, TRUE, FALSE,
4542 EL_CHAR('V'), -1, -1
4545 Xalpha_w, TRUE, FALSE,
4546 EL_CHAR('W'), -1, -1
4549 Xalpha_x, TRUE, FALSE,
4550 EL_CHAR('X'), -1, -1
4553 Xalpha_y, TRUE, FALSE,
4554 EL_CHAR('Y'), -1, -1
4557 Xalpha_z, TRUE, FALSE,
4558 EL_CHAR('Z'), -1, -1
4561 Xalpha_arrow_e, TRUE, FALSE,
4562 EL_CHAR('>'), -1, -1
4565 Xalpha_arrow_w, TRUE, FALSE,
4566 EL_CHAR('<'), -1, -1
4569 Xalpha_copyr, TRUE, FALSE,
4570 EL_CHAR('©'), -1, -1
4573 Xalpha_copyr, TRUE, FALSE,
4574 EL_CHAR('©'), -1, -1
4578 Xboom_bug, FALSE, FALSE,
4579 EL_BUG, ACTION_EXPLODING, -1
4582 Xboom_bomb, FALSE, FALSE,
4583 EL_BOMB, ACTION_EXPLODING, -1
4586 Xboom_android, FALSE, FALSE,
4587 EL_EMC_ANDROID, ACTION_OTHER, -1
4590 Xboom_1, FALSE, FALSE,
4591 EL_DEFAULT, ACTION_EXPLODING, -1
4594 Xboom_2, FALSE, FALSE,
4595 EL_DEFAULT, ACTION_EXPLODING, -1
4598 Znormal, FALSE, FALSE,
4602 Zdynamite, FALSE, FALSE,
4606 Zplayer, FALSE, FALSE,
4610 ZBORDER, FALSE, FALSE,
4620 int map_element_RND_to_EM(int element_rnd)
4622 static unsigned short mapping_RND_to_EM[NUM_FILE_ELEMENTS];
4623 static boolean mapping_initialized = FALSE;
4625 if (!mapping_initialized)
4629 /* return "Xalpha_quest" for all undefined elements in mapping array */
4630 for (i = 0; i < NUM_FILE_ELEMENTS; i++)
4631 mapping_RND_to_EM[i] = Xalpha_quest;
4633 for (i = 0; mapping_EM_to_RND_list[i].element_em != -1; i++)
4634 if (mapping_EM_to_RND_list[i].is_rnd_to_em_mapping)
4635 mapping_RND_to_EM[mapping_EM_to_RND_list[i].element_rnd] =
4636 mapping_EM_to_RND_list[i].element_em;
4638 mapping_initialized = TRUE;
4641 if (element_rnd >= 0 && element_rnd < NUM_FILE_ELEMENTS)
4642 return mapping_RND_to_EM[element_rnd];
4644 Error(ERR_WARN, "invalid RND level element %d", element_rnd);
4649 int map_element_EM_to_RND(int element_em)
4651 static unsigned short mapping_EM_to_RND[TILE_MAX];
4652 static boolean mapping_initialized = FALSE;
4654 if (!mapping_initialized)
4658 /* return "EL_UNKNOWN" for all undefined elements in mapping array */
4659 for (i = 0; i < TILE_MAX; i++)
4660 mapping_EM_to_RND[i] = EL_UNKNOWN;
4662 for (i = 0; mapping_EM_to_RND_list[i].element_em != -1; i++)
4663 mapping_EM_to_RND[mapping_EM_to_RND_list[i].element_em] =
4664 mapping_EM_to_RND_list[i].element_rnd;
4666 mapping_initialized = TRUE;
4669 if (element_em >= 0 && element_em < TILE_MAX)
4670 return mapping_EM_to_RND[element_em];
4672 Error(ERR_WARN, "invalid EM level element %d", element_em);
4679 int map_element_RND_to_EM(int element_rnd)
4681 static unsigned short mapping_RND_to_EM[NUM_FILE_ELEMENTS];
4682 static boolean mapping_initialized = FALSE;
4689 mapping_RND_to_EM_list[] =
4691 { Xblank, EL_EMPTY },
4692 { Xstone, EL_ROCK },
4694 { Xbug_n, EL_BUG_UP },
4695 { Xbug_e, EL_BUG_RIGHT },
4696 { Xbug_s, EL_BUG_DOWN },
4697 { Xbug_w, EL_BUG_LEFT },
4698 { Xtank_n, EL_SPACESHIP_UP },
4699 { Xtank_e, EL_SPACESHIP_RIGHT },
4700 { Xtank_s, EL_SPACESHIP_DOWN },
4701 { Xtank_w, EL_SPACESHIP_LEFT },
4702 { Xandroid, EL_EMC_ANDROID },
4703 { Xandroid_1_n, EL_EMC_ANDROID_UP },
4704 { Xandroid_1_e, EL_EMC_ANDROID_RIGHT },
4705 { Xandroid_1_w, EL_EMC_ANDROID_LEFT },
4706 { Xandroid_1_s, EL_EMC_ANDROID_DOWN },
4707 { Xspring, EL_SPRING },
4708 { Xeater_n, EL_YAMYAM },
4709 { Xalien, EL_ROBOT },
4710 { Xemerald, EL_EMERALD },
4711 { Xdiamond, EL_DIAMOND },
4712 { Xdrip_fall, EL_AMOEBA_DROP },
4714 { Xballoon, EL_BALLOON },
4715 { Xgrass, EL_EMC_GRASS },
4717 { Xacid_ne, EL_ACID_POOL_TOPRIGHT },
4718 { Xacid_se, EL_ACID_POOL_BOTTOMRIGHT },
4719 { Xacid_s, EL_ACID_POOL_BOTTOM },
4720 { Xacid_sw, EL_ACID_POOL_BOTTOMLEFT },
4721 { Xacid_nw, EL_ACID_POOL_TOPLEFT },
4722 { Xacid_1, EL_ACID },
4723 { Xball_1, EL_EMC_MAGIC_BALL },
4724 { Xgrow_ns, EL_EMC_GROW },
4725 { Xwonderwall, EL_MAGIC_WALL },
4726 { Xamoeba_1, EL_AMOEBA_WET },
4727 { Xdoor_1, EL_EM_GATE_1 },
4728 { Xdoor_2, EL_EM_GATE_2 },
4729 { Xdoor_3, EL_EM_GATE_3 },
4730 { Xdoor_4, EL_EM_GATE_4 },
4731 { Xdoor_5, EL_EMC_GATE_5 },
4732 { Xdoor_6, EL_EMC_GATE_6 },
4733 { Xdoor_7, EL_EMC_GATE_7 },
4734 { Xdoor_8, EL_EMC_GATE_8 },
4735 { Xkey_1, EL_EM_KEY_1 },
4736 { Xkey_2, EL_EM_KEY_2 },
4737 { Xkey_3, EL_EM_KEY_3 },
4738 { Xkey_4, EL_EM_KEY_4 },
4739 { Xkey_5, EL_EMC_KEY_5 },
4740 { Xkey_6, EL_EMC_KEY_6 },
4741 { Xkey_7, EL_EMC_KEY_7 },
4742 { Xkey_8, EL_EMC_KEY_8 },
4743 { Xwind_n, EL_BALLOON_SWITCH_UP },
4744 { Xwind_e, EL_BALLOON_SWITCH_RIGHT },
4745 { Xwind_s, EL_BALLOON_SWITCH_DOWN },
4746 { Xwind_w, EL_BALLOON_SWITCH_LEFT },
4747 { Xwind_nesw, EL_BALLOON_SWITCH_ANY },
4748 { Xwind_stop, EL_BALLOON_SWITCH_NONE },
4749 { Xexit, EL_EXIT_CLOSED },
4750 { Xexit_1, EL_EXIT_OPEN },
4751 { Xdynamite, EL_DYNAMITE },
4752 { Xdynamite_1, EL_DYNAMITE_ACTIVE },
4753 { Xbumper, EL_EMC_BUMPER },
4754 { Xwheel, EL_ROBOT_WHEEL },
4755 { Xswitch, EL_UNKNOWN },
4756 { Xsand, EL_QUICKSAND_EMPTY },
4757 { Xsand_stone, EL_QUICKSAND_FULL },
4758 { Xplant, EL_EMC_PLANT },
4759 { Xlenses, EL_EMC_LENSES },
4760 { Xmagnify, EL_EMC_MAGNIFIER },
4761 { Xdripper, EL_UNKNOWN },
4762 { Xfake_blank, EL_INVISIBLE_WALL },
4763 { Xfake_grass, EL_INVISIBLE_SAND },
4764 { Xfake_door_1, EL_EM_GATE_1_GRAY },
4765 { Xfake_door_2, EL_EM_GATE_2_GRAY },
4766 { Xfake_door_3, EL_EM_GATE_3_GRAY },
4767 { Xfake_door_4, EL_EM_GATE_4_GRAY },
4768 { Xfake_door_5, EL_EMC_GATE_5_GRAY },
4769 { Xfake_door_6, EL_EMC_GATE_6_GRAY },
4770 { Xfake_door_7, EL_EMC_GATE_7_GRAY },
4771 { Xfake_door_8, EL_EMC_GATE_8_GRAY },
4772 { Xsteel_1, EL_STEELWALL },
4773 { Xsteel_2, EL_UNKNOWN },
4774 { Xsteel_3, EL_EMC_STEELWALL_1 },
4775 { Xsteel_4, EL_UNKNOWN },
4776 { Xwall_1, EL_WALL },
4777 { Xwall_2, EL_UNKNOWN },
4778 { Xwall_3, EL_UNKNOWN },
4779 { Xwall_4, EL_UNKNOWN },
4780 { Xround_wall_1, EL_WALL_SLIPPERY },
4781 { Xround_wall_2, EL_UNKNOWN },
4782 { Xround_wall_3, EL_UNKNOWN },
4783 { Xround_wall_4, EL_UNKNOWN },
4784 { Xdecor_1, EL_UNKNOWN },
4785 { Xdecor_2, EL_EMC_WALL_6 },
4786 { Xdecor_3, EL_EMC_WALL_4 },
4787 { Xdecor_4, EL_EMC_WALL_5 },
4788 { Xdecor_5, EL_EMC_WALL_7 },
4789 { Xdecor_6, EL_EMC_WALL_8 },
4790 { Xdecor_7, EL_UNKNOWN },
4791 { Xdecor_8, EL_EMC_WALL_1 },
4792 { Xdecor_9, EL_EMC_WALL_2 },
4793 { Xdecor_10, EL_EMC_WALL_3 },
4794 { Xdecor_11, EL_UNKNOWN },
4795 { Xdecor_12, EL_UNKNOWN },
4796 { Xalpha_0, EL_CHAR('0') },
4797 { Xalpha_1, EL_CHAR('1') },
4798 { Xalpha_2, EL_CHAR('2') },
4799 { Xalpha_3, EL_CHAR('3') },
4800 { Xalpha_4, EL_CHAR('4') },
4801 { Xalpha_5, EL_CHAR('5') },
4802 { Xalpha_6, EL_CHAR('6') },
4803 { Xalpha_7, EL_CHAR('7') },
4804 { Xalpha_8, EL_CHAR('8') },
4805 { Xalpha_9, EL_CHAR('9') },
4806 { Xalpha_excla, EL_CHAR('!') },
4807 { Xalpha_quote, EL_CHAR('"') },
4808 { Xalpha_comma, EL_CHAR(',') },
4809 { Xalpha_minus, EL_CHAR('-') },
4810 { Xalpha_perio, EL_CHAR('.') },
4811 { Xalpha_colon, EL_CHAR(':') },
4812 { Xalpha_quest, EL_CHAR('?') },
4813 { Xalpha_a, EL_CHAR('A') },
4814 { Xalpha_b, EL_CHAR('B') },
4815 { Xalpha_c, EL_CHAR('C') },
4816 { Xalpha_d, EL_CHAR('D') },
4817 { Xalpha_e, EL_CHAR('E') },
4818 { Xalpha_f, EL_CHAR('F') },
4819 { Xalpha_g, EL_CHAR('G') },
4820 { Xalpha_h, EL_CHAR('H') },
4821 { Xalpha_i, EL_CHAR('I') },
4822 { Xalpha_j, EL_CHAR('J') },
4823 { Xalpha_k, EL_CHAR('K') },
4824 { Xalpha_l, EL_CHAR('L') },
4825 { Xalpha_m, EL_CHAR('M') },
4826 { Xalpha_n, EL_CHAR('N') },
4827 { Xalpha_o, EL_CHAR('O') },
4828 { Xalpha_p, EL_CHAR('P') },
4829 { Xalpha_q, EL_CHAR('Q') },
4830 { Xalpha_r, EL_CHAR('R') },
4831 { Xalpha_s, EL_CHAR('S') },
4832 { Xalpha_t, EL_CHAR('T') },
4833 { Xalpha_u, EL_CHAR('U') },
4834 { Xalpha_v, EL_CHAR('V') },
4835 { Xalpha_w, EL_CHAR('W') },
4836 { Xalpha_x, EL_CHAR('X') },
4837 { Xalpha_y, EL_CHAR('Y') },
4838 { Xalpha_z, EL_CHAR('Z') },
4839 { Xalpha_arrow_e, EL_CHAR('>') },
4840 { Xalpha_arrow_w, EL_CHAR('<') },
4841 { Xalpha_copyr, EL_CHAR('©') },
4843 { Zplayer, EL_PLAYER_1 },
4844 { Zplayer, EL_PLAYER_2 },
4845 { Zplayer, EL_PLAYER_3 },
4846 { Zplayer, EL_PLAYER_4 },
4848 { ZBORDER, EL_EMC_LEVEL_BORDER },
4853 if (!mapping_initialized)
4857 /* return "Xalpha_quest" for all undefined elements in mapping array */
4858 for (i = 0; i < NUM_FILE_ELEMENTS; i++)
4859 mapping_RND_to_EM[i] = Xalpha_quest;
4861 for (i = 0; mapping_RND_to_EM_list[i].element_rnd != -1; i++)
4862 mapping_RND_to_EM[mapping_RND_to_EM_list[i].element_rnd] =
4863 mapping_RND_to_EM_list[i].element_em;
4865 mapping_initialized = TRUE;
4868 if (element_rnd >= 0 && element_rnd < NUM_FILE_ELEMENTS)
4869 return mapping_RND_to_EM[element_rnd];
4871 Error(ERR_WARN, "invalid RND level element %d", element_rnd);
4876 int map_element_EM_to_RND(int element_em)
4878 static unsigned short mapping_EM_to_RND[TILE_MAX];
4879 static boolean mapping_initialized = FALSE;
4886 mapping_EM_to_RND_list[] =
4888 { Xblank, EL_EMPTY },
4889 { Yacid_splash_eB, EL_EMPTY },
4890 { Yacid_splash_wB, EL_EMPTY },
4892 #ifdef EM_ENGINE_BAD_ROLL
4893 { Xstone_force_e, EL_ROCK },
4894 { Xstone_force_w, EL_ROCK },
4895 { Xnut_force_e, EL_NUT },
4896 { Xnut_force_w, EL_NUT },
4897 { Xspring_force_e, EL_SPRING },
4898 { Xspring_force_w, EL_SPRING },
4899 { Xemerald_force_e, EL_EMERALD },
4900 { Xemerald_force_w, EL_EMERALD },
4901 { Xdiamond_force_e, EL_DIAMOND },
4902 { Xdiamond_force_w, EL_DIAMOND },
4903 { Xbomb_force_e, EL_BOMB },
4904 { Xbomb_force_w, EL_BOMB },
4907 { Xstone, EL_ROCK },
4908 { Xstone_pause, EL_ROCK },
4909 { Xstone_fall, EL_ROCK },
4910 { Ystone_s, EL_ROCK },
4911 { Ystone_sB, EL_ROCK },
4912 { Ystone_e, EL_ROCK },
4913 { Ystone_eB, EL_ROCK },
4914 { Ystone_w, EL_ROCK },
4915 { Ystone_wB, EL_ROCK },
4917 { Xnut_pause, EL_NUT },
4918 { Xnut_fall, EL_NUT },
4920 { Ynut_sB, EL_NUT },
4922 { Ynut_eB, EL_NUT },
4924 { Ynut_wB, EL_NUT },
4925 { Xbug_n, EL_BUG_UP },
4926 { Xbug_e, EL_BUG_RIGHT },
4927 { Xbug_s, EL_BUG_DOWN },
4928 { Xbug_w, EL_BUG_LEFT },
4929 { Xbug_gon, EL_BUG_UP },
4930 { Xbug_goe, EL_BUG_RIGHT },
4931 { Xbug_gos, EL_BUG_DOWN },
4932 { Xbug_gow, EL_BUG_LEFT },
4933 { Ybug_n, EL_BUG_UP },
4934 { Ybug_nB, EL_BUG_UP },
4935 { Ybug_e, EL_BUG_RIGHT },
4936 { Ybug_eB, EL_BUG_RIGHT },
4937 { Ybug_s, EL_BUG_DOWN },
4938 { Ybug_sB, EL_BUG_DOWN },
4939 { Ybug_w, EL_BUG_LEFT },
4940 { Ybug_wB, EL_BUG_LEFT },
4941 { Ybug_w_n, EL_BUG_UP },
4942 { Ybug_n_e, EL_BUG_RIGHT },
4943 { Ybug_e_s, EL_BUG_DOWN },
4944 { Ybug_s_w, EL_BUG_LEFT },
4945 { Ybug_e_n, EL_BUG_UP },
4946 { Ybug_s_e, EL_BUG_RIGHT },
4947 { Ybug_w_s, EL_BUG_DOWN },
4948 { Ybug_n_w, EL_BUG_LEFT },
4949 { Ybug_stone, EL_ROCK },
4950 { Ybug_spring, EL_SPRING },
4951 { Xtank_n, EL_SPACESHIP_UP },
4952 { Xtank_e, EL_SPACESHIP_RIGHT },
4953 { Xtank_s, EL_SPACESHIP_DOWN },
4954 { Xtank_w, EL_SPACESHIP_LEFT },
4955 { Xtank_gon, EL_SPACESHIP_UP },
4956 { Xtank_goe, EL_SPACESHIP_RIGHT },
4957 { Xtank_gos, EL_SPACESHIP_DOWN },
4958 { Xtank_gow, EL_SPACESHIP_LEFT },
4959 { Ytank_n, EL_SPACESHIP_UP },
4960 { Ytank_nB, EL_SPACESHIP_UP },
4961 { Ytank_e, EL_SPACESHIP_RIGHT },
4962 { Ytank_eB, EL_SPACESHIP_RIGHT },
4963 { Ytank_s, EL_SPACESHIP_DOWN },
4964 { Ytank_sB, EL_SPACESHIP_DOWN },
4965 { Ytank_w, EL_SPACESHIP_LEFT },
4966 { Ytank_wB, EL_SPACESHIP_LEFT },
4967 { Ytank_w_n, EL_SPACESHIP_UP },
4968 { Ytank_n_e, EL_SPACESHIP_RIGHT },
4969 { Ytank_e_s, EL_SPACESHIP_DOWN },
4970 { Ytank_s_w, EL_SPACESHIP_LEFT },
4971 { Ytank_e_n, EL_SPACESHIP_UP },
4972 { Ytank_s_e, EL_SPACESHIP_RIGHT },
4973 { Ytank_w_s, EL_SPACESHIP_DOWN },
4974 { Ytank_n_w, EL_SPACESHIP_LEFT },
4975 { Ytank_stone, EL_ROCK },
4976 { Ytank_spring, EL_SPRING },
4977 { Xandroid, EL_EMC_ANDROID },
4978 { Xandroid_1_n, EL_EMC_ANDROID_UP },
4979 { Xandroid_2_n, EL_EMC_ANDROID_UP },
4980 { Xandroid_1_e, EL_EMC_ANDROID_RIGHT },
4981 { Xandroid_2_e, EL_EMC_ANDROID_RIGHT },
4982 { Xandroid_1_w, EL_EMC_ANDROID_LEFT },
4983 { Xandroid_2_w, EL_EMC_ANDROID_LEFT },
4984 { Xandroid_1_s, EL_EMC_ANDROID_DOWN },
4985 { Xandroid_2_s, EL_EMC_ANDROID_DOWN },
4986 { Yandroid_n, EL_EMC_ANDROID_UP },
4987 { Yandroid_nB, EL_EMC_ANDROID_UP },
4988 { Yandroid_ne, EL_EMC_ANDROID_RIGHT_UP },
4989 { Yandroid_neB, EL_EMC_ANDROID_RIGHT_UP },
4990 { Yandroid_e, EL_EMC_ANDROID_RIGHT },
4991 { Yandroid_eB, EL_EMC_ANDROID_RIGHT },
4992 { Yandroid_se, EL_EMC_ANDROID_RIGHT_DOWN },
4993 { Yandroid_seB, EL_EMC_ANDROID_RIGHT_DOWN },
4994 { Yandroid_s, EL_EMC_ANDROID_DOWN },
4995 { Yandroid_sB, EL_EMC_ANDROID_DOWN },
4996 { Yandroid_sw, EL_EMC_ANDROID_LEFT_DOWN },
4997 { Yandroid_swB, EL_EMC_ANDROID_LEFT_DOWN },
4998 { Yandroid_w, EL_EMC_ANDROID_LEFT },
4999 { Yandroid_wB, EL_EMC_ANDROID_LEFT },
5000 { Yandroid_nw, EL_EMC_ANDROID_LEFT_UP },
5001 { Yandroid_nwB, EL_EMC_ANDROID_LEFT_UP },
5002 { Xspring, EL_SPRING },
5003 { Xspring_pause, EL_SPRING },
5004 { Xspring_e, EL_SPRING },
5005 { Xspring_w, EL_SPRING },
5006 { Xspring_fall, EL_SPRING },
5007 { Yspring_s, EL_SPRING },
5008 { Yspring_sB, EL_SPRING },
5009 { Yspring_e, EL_SPRING },
5010 { Yspring_eB, EL_SPRING },
5011 { Yspring_w, EL_SPRING },
5012 { Yspring_wB, EL_SPRING },
5013 { Yspring_kill_e, EL_SPRING },
5014 { Yspring_kill_eB, EL_SPRING },
5015 { Yspring_kill_w, EL_SPRING },
5016 { Yspring_kill_wB, EL_SPRING },
5017 { Xeater_n, EL_YAMYAM },
5018 { Xeater_e, EL_YAMYAM },
5019 { Xeater_w, EL_YAMYAM },
5020 { Xeater_s, EL_YAMYAM },
5021 { Yeater_n, EL_YAMYAM },
5022 { Yeater_nB, EL_YAMYAM },
5023 { Yeater_e, EL_YAMYAM },
5024 { Yeater_eB, EL_YAMYAM },
5025 { Yeater_s, EL_YAMYAM },
5026 { Yeater_sB, EL_YAMYAM },
5027 { Yeater_w, EL_YAMYAM },
5028 { Yeater_wB, EL_YAMYAM },
5029 { Yeater_stone, EL_ROCK },
5030 { Yeater_spring, EL_SPRING },
5031 { Xalien, EL_ROBOT },
5032 { Xalien_pause, EL_ROBOT },
5033 { Yalien_n, EL_ROBOT },
5034 { Yalien_nB, EL_ROBOT },
5035 { Yalien_e, EL_ROBOT },
5036 { Yalien_eB, EL_ROBOT },
5037 { Yalien_s, EL_ROBOT },
5038 { Yalien_sB, EL_ROBOT },
5039 { Yalien_w, EL_ROBOT },
5040 { Yalien_wB, EL_ROBOT },
5041 { Yalien_stone, EL_ROCK },
5042 { Yalien_spring, EL_SPRING },
5043 { Xemerald, EL_EMERALD },
5044 { Xemerald_pause, EL_EMERALD },
5045 { Xemerald_fall, EL_EMERALD },
5046 { Xemerald_shine, EL_EMERALD },
5047 { Yemerald_s, EL_EMERALD },
5048 { Yemerald_sB, EL_EMERALD },
5049 { Yemerald_e, EL_EMERALD },
5050 { Yemerald_eB, EL_EMERALD },
5051 { Yemerald_w, EL_EMERALD },
5052 { Yemerald_wB, EL_EMERALD },
5053 { Yemerald_eat, EL_EMERALD },
5054 { Yemerald_stone, EL_ROCK },
5055 { Xdiamond, EL_DIAMOND },
5056 { Xdiamond_pause, EL_DIAMOND },
5057 { Xdiamond_fall, EL_DIAMOND },
5058 { Xdiamond_shine, EL_DIAMOND },
5059 { Ydiamond_s, EL_DIAMOND },
5060 { Ydiamond_sB, EL_DIAMOND },
5061 { Ydiamond_e, EL_DIAMOND },
5062 { Ydiamond_eB, EL_DIAMOND },
5063 { Ydiamond_w, EL_DIAMOND },
5064 { Ydiamond_wB, EL_DIAMOND },
5065 { Ydiamond_eat, EL_DIAMOND },
5066 { Ydiamond_stone, EL_ROCK },
5067 { Xdrip_fall, EL_AMOEBA_DROP },
5068 { Xdrip_stretch, EL_AMOEBA_DROP },
5069 { Xdrip_stretchB, EL_AMOEBA_DROP },
5070 { Xdrip_eat, EL_AMOEBA_DROP },
5071 { Ydrip_s1, EL_AMOEBA_DROP },
5072 { Ydrip_s1B, EL_AMOEBA_DROP },
5073 { Ydrip_s2, EL_AMOEBA_DROP },
5074 { Ydrip_s2B, EL_AMOEBA_DROP },
5076 { Xbomb_pause, EL_BOMB },
5077 { Xbomb_fall, EL_BOMB },
5078 { Ybomb_s, EL_BOMB },
5079 { Ybomb_sB, EL_BOMB },
5080 { Ybomb_e, EL_BOMB },
5081 { Ybomb_eB, EL_BOMB },
5082 { Ybomb_w, EL_BOMB },
5083 { Ybomb_wB, EL_BOMB },
5084 { Ybomb_eat, EL_BOMB },
5085 { Xballoon, EL_BALLOON },
5086 { Yballoon_n, EL_BALLOON },
5087 { Yballoon_nB, EL_BALLOON },
5088 { Yballoon_e, EL_BALLOON },
5089 { Yballoon_eB, EL_BALLOON },
5090 { Yballoon_s, EL_BALLOON },
5091 { Yballoon_sB, EL_BALLOON },
5092 { Yballoon_w, EL_BALLOON },
5093 { Yballoon_wB, EL_BALLOON },
5094 { Xgrass, EL_SAND },
5095 { Ygrass_nB, EL_SAND },
5096 { Ygrass_eB, EL_SAND },
5097 { Ygrass_sB, EL_SAND },
5098 { Ygrass_wB, EL_SAND },
5100 { Ydirt_nB, EL_SAND },
5101 { Ydirt_eB, EL_SAND },
5102 { Ydirt_sB, EL_SAND },
5103 { Ydirt_wB, EL_SAND },
5104 { Xacid_ne, EL_ACID_POOL_TOPRIGHT },
5105 { Xacid_se, EL_ACID_POOL_BOTTOMRIGHT },
5106 { Xacid_s, EL_ACID_POOL_BOTTOM },
5107 { Xacid_sw, EL_ACID_POOL_BOTTOMLEFT },
5108 { Xacid_nw, EL_ACID_POOL_TOPLEFT },
5109 { Xacid_1, EL_ACID },
5110 { Xacid_2, EL_ACID },
5111 { Xacid_3, EL_ACID },
5112 { Xacid_4, EL_ACID },
5113 { Xacid_5, EL_ACID },
5114 { Xacid_6, EL_ACID },
5115 { Xacid_7, EL_ACID },
5116 { Xacid_8, EL_ACID },
5117 { Xball_1, EL_EMC_MAGIC_BALL },
5118 { Xball_1B, EL_EMC_MAGIC_BALL },
5119 { Xball_2, EL_EMC_MAGIC_BALL },
5120 { Xball_2B, EL_EMC_MAGIC_BALL },
5121 { Yball_eat, EL_EMC_MAGIC_BALL },
5122 { Xgrow_ns, EL_EMC_GROW },
5123 { Ygrow_ns_eat, EL_EMC_GROW },
5124 { Xgrow_ew, EL_EMC_GROW },
5125 { Ygrow_ew_eat, EL_EMC_GROW },
5126 { Xwonderwall, EL_MAGIC_WALL },
5127 { XwonderwallB, EL_MAGIC_WALL },
5128 { Xamoeba_1, EL_AMOEBA_WET },
5129 { Xamoeba_2, EL_AMOEBA_WET },
5130 { Xamoeba_3, EL_AMOEBA_WET },
5131 { Xamoeba_4, EL_AMOEBA_WET },
5132 { Xamoeba_5, EL_AMOEBA_WET },
5133 { Xamoeba_6, EL_AMOEBA_WET },
5134 { Xamoeba_7, EL_AMOEBA_WET },
5135 { Xamoeba_8, EL_AMOEBA_WET },
5136 { Xdoor_1, EL_EM_GATE_1 },
5137 { Xdoor_2, EL_EM_GATE_2 },
5138 { Xdoor_3, EL_EM_GATE_3 },
5139 { Xdoor_4, EL_EM_GATE_4 },
5140 { Xdoor_5, EL_EMC_GATE_5 },
5141 { Xdoor_6, EL_EMC_GATE_6 },
5142 { Xdoor_7, EL_EMC_GATE_7 },
5143 { Xdoor_8, EL_EMC_GATE_8 },
5144 { Xkey_1, EL_EM_KEY_1 },
5145 { Xkey_2, EL_EM_KEY_2 },
5146 { Xkey_3, EL_EM_KEY_3 },
5147 { Xkey_4, EL_EM_KEY_4 },
5148 { Xkey_5, EL_EMC_KEY_5 },
5149 { Xkey_6, EL_EMC_KEY_6 },
5150 { Xkey_7, EL_EMC_KEY_7 },
5151 { Xkey_8, EL_EMC_KEY_8 },
5152 { Xwind_n, EL_BALLOON_SWITCH_UP },
5153 { Xwind_e, EL_BALLOON_SWITCH_RIGHT },
5154 { Xwind_s, EL_BALLOON_SWITCH_DOWN },
5155 { Xwind_w, EL_BALLOON_SWITCH_LEFT },
5156 { Xwind_nesw, EL_BALLOON_SWITCH_ANY },
5157 { Xwind_stop, EL_BALLOON_SWITCH_NONE },
5158 { Xexit, EL_EXIT_CLOSED },
5159 { Xexit_1, EL_EXIT_OPEN },
5160 { Xexit_2, EL_EXIT_OPEN },
5161 { Xexit_3, EL_EXIT_OPEN },
5162 { Xdynamite, EL_DYNAMITE },
5163 { Ydynamite_eat, EL_DYNAMITE },
5164 { Xdynamite_1, EL_DYNAMITE_ACTIVE },
5165 { Xdynamite_2, EL_DYNAMITE_ACTIVE },
5166 { Xdynamite_3, EL_DYNAMITE_ACTIVE },
5167 { Xdynamite_4, EL_DYNAMITE_ACTIVE },
5168 { Xbumper, EL_EMC_BUMPER },
5169 { XbumperB, EL_EMC_BUMPER },
5170 { Xwheel, EL_ROBOT_WHEEL },
5171 { XwheelB, EL_ROBOT_WHEEL },
5172 { Xswitch, EL_UNKNOWN },
5173 { XswitchB, EL_UNKNOWN },
5174 { Xsand, EL_QUICKSAND_EMPTY },
5175 { Xsand_stone, EL_QUICKSAND_FULL },
5176 { Xsand_stonein_1, EL_QUICKSAND_FULL },
5177 { Xsand_stonein_2, EL_QUICKSAND_FULL },
5178 { Xsand_stonein_3, EL_QUICKSAND_FULL },
5179 { Xsand_stonein_4, EL_QUICKSAND_FULL },
5180 { Xsand_stonesand_1, EL_QUICKSAND_FULL },
5181 { Xsand_stonesand_2, EL_QUICKSAND_FULL },
5182 { Xsand_stonesand_3, EL_QUICKSAND_FULL },
5183 { Xsand_stonesand_4, EL_QUICKSAND_FULL },
5184 { Xsand_stoneout_1, EL_QUICKSAND_FULL },
5185 { Xsand_stoneout_2, EL_QUICKSAND_FULL },
5186 { Xsand_sandstone_1, EL_QUICKSAND_FULL },
5187 { Xsand_sandstone_2, EL_QUICKSAND_FULL },
5188 { Xsand_sandstone_3, EL_QUICKSAND_FULL },
5189 { Xsand_sandstone_4, EL_QUICKSAND_FULL },
5190 { Xplant, EL_EMC_PLANT },
5191 { Yplant, EL_EMC_PLANT },
5192 { Xlenses, EL_EMC_LENSES },
5193 { Xmagnify, EL_EMC_MAGNIFIER },
5194 { Xdripper, EL_UNKNOWN },
5195 { XdripperB, EL_UNKNOWN },
5196 { Xfake_blank, EL_INVISIBLE_WALL },
5197 { Xfake_blankB, EL_INVISIBLE_WALL },
5198 { Xfake_grass, EL_INVISIBLE_SAND },
5199 { Xfake_grassB, EL_INVISIBLE_SAND },
5200 { Xfake_door_1, EL_EM_GATE_1_GRAY },
5201 { Xfake_door_2, EL_EM_GATE_2_GRAY },
5202 { Xfake_door_3, EL_EM_GATE_3_GRAY },
5203 { Xfake_door_4, EL_EM_GATE_4_GRAY },
5204 { Xfake_door_5, EL_EMC_GATE_5_GRAY },
5205 { Xfake_door_6, EL_EMC_GATE_6_GRAY },
5206 { Xfake_door_7, EL_EMC_GATE_7_GRAY },
5207 { Xfake_door_8, EL_EMC_GATE_8_GRAY },
5208 { Xsteel_1, EL_STEELWALL },
5209 { Xsteel_2, EL_UNKNOWN },
5210 { Xsteel_3, EL_EMC_STEELWALL_1 },
5211 { Xsteel_4, EL_UNKNOWN },
5212 { Xwall_1, EL_WALL },
5213 { Xwall_2, EL_UNKNOWN },
5214 { Xwall_3, EL_UNKNOWN },
5215 { Xwall_4, EL_UNKNOWN },
5216 { Xround_wall_1, EL_WALL_SLIPPERY },
5217 { Xround_wall_2, EL_UNKNOWN },
5218 { Xround_wall_3, EL_UNKNOWN },
5219 { Xround_wall_4, EL_UNKNOWN },
5220 { Xdecor_1, EL_UNKNOWN },
5221 { Xdecor_2, EL_EMC_WALL_6 },
5222 { Xdecor_3, EL_EMC_WALL_4 },
5223 { Xdecor_4, EL_EMC_WALL_5 },
5224 { Xdecor_5, EL_EMC_WALL_7 },
5225 { Xdecor_6, EL_EMC_WALL_8 },
5226 { Xdecor_7, EL_UNKNOWN },
5227 { Xdecor_8, EL_EMC_WALL_1 },
5228 { Xdecor_9, EL_EMC_WALL_2 },
5229 { Xdecor_10, EL_EMC_WALL_3 },
5230 { Xdecor_11, EL_UNKNOWN },
5231 { Xdecor_12, EL_UNKNOWN },
5232 { Xalpha_0, EL_CHAR('0') },
5233 { Xalpha_1, EL_CHAR('1') },
5234 { Xalpha_2, EL_CHAR('2') },
5235 { Xalpha_3, EL_CHAR('3') },
5236 { Xalpha_4, EL_CHAR('4') },
5237 { Xalpha_5, EL_CHAR('5') },
5238 { Xalpha_6, EL_CHAR('6') },
5239 { Xalpha_7, EL_CHAR('7') },
5240 { Xalpha_8, EL_CHAR('8') },
5241 { Xalpha_9, EL_CHAR('9') },
5242 { Xalpha_excla, EL_CHAR('!') },
5243 { Xalpha_quote, EL_CHAR('"') },
5244 { Xalpha_comma, EL_CHAR(',') },
5245 { Xalpha_minus, EL_CHAR('-') },
5246 { Xalpha_perio, EL_CHAR('.') },
5247 { Xalpha_colon, EL_CHAR(':') },
5248 { Xalpha_quest, EL_CHAR('?') },
5249 { Xalpha_a, EL_CHAR('A') },
5250 { Xalpha_b, EL_CHAR('B') },
5251 { Xalpha_c, EL_CHAR('C') },
5252 { Xalpha_d, EL_CHAR('D') },
5253 { Xalpha_e, EL_CHAR('E') },
5254 { Xalpha_f, EL_CHAR('F') },
5255 { Xalpha_g, EL_CHAR('G') },
5256 { Xalpha_h, EL_CHAR('H') },
5257 { Xalpha_i, EL_CHAR('I') },
5258 { Xalpha_j, EL_CHAR('J') },
5259 { Xalpha_k, EL_CHAR('K') },
5260 { Xalpha_l, EL_CHAR('L') },
5261 { Xalpha_m, EL_CHAR('M') },
5262 { Xalpha_n, EL_CHAR('N') },
5263 { Xalpha_o, EL_CHAR('O') },
5264 { Xalpha_p, EL_CHAR('P') },
5265 { Xalpha_q, EL_CHAR('Q') },
5266 { Xalpha_r, EL_CHAR('R') },
5267 { Xalpha_s, EL_CHAR('S') },
5268 { Xalpha_t, EL_CHAR('T') },
5269 { Xalpha_u, EL_CHAR('U') },
5270 { Xalpha_v, EL_CHAR('V') },
5271 { Xalpha_w, EL_CHAR('W') },
5272 { Xalpha_x, EL_CHAR('X') },
5273 { Xalpha_y, EL_CHAR('Y') },
5274 { Xalpha_z, EL_CHAR('Z') },
5275 { Xalpha_arrow_e, EL_CHAR('>') },
5276 { Xalpha_arrow_w, EL_CHAR('<') },
5277 { Xalpha_copyr, EL_CHAR('©') },
5279 { Zplayer, EL_PLAYER_1 },
5281 { ZBORDER, EL_EMC_LEVEL_BORDER },
5286 if (!mapping_initialized)
5290 /* return "EL_UNKNOWN" for all undefined elements in mapping array */
5291 for (i = 0; i < TILE_MAX; i++)
5292 mapping_EM_to_RND[i] = EL_UNKNOWN;
5294 for (i = 0; mapping_EM_to_RND_list[i].element_em != -1; i++)
5295 mapping_EM_to_RND[mapping_EM_to_RND_list[i].element_em] =
5296 mapping_EM_to_RND_list[i].element_rnd;
5298 mapping_initialized = TRUE;
5301 if (element_em >= 0 && element_em < TILE_MAX)
5302 return mapping_EM_to_RND[element_em];
5304 Error(ERR_WARN, "invalid EM level element %d", element_em);
5311 int get_next_element(int element)
5315 case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL;
5316 case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY;
5317 case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL;
5318 case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_ACTIVE;
5319 case EL_BD_MAGIC_WALL_FILLING: return EL_BD_MAGIC_WALL_FULL;
5320 case EL_BD_MAGIC_WALL_EMPTYING: return EL_BD_MAGIC_WALL_ACTIVE;
5321 case EL_AMOEBA_DROPPING: return EL_AMOEBA_WET;
5323 default: return element;
5327 int el_act_dir2img(int element, int action, int direction)
5329 element = GFX_ELEMENT(element);
5330 direction = MV_DIR_BIT(direction); /* default: MV_NO_MOVING => MV_DOWN */
5332 return element_info[element].direction_graphic[action][direction];
5335 static int el_act_dir2crm(int element, int action, int direction)
5337 element = GFX_ELEMENT(element);
5338 direction = MV_DIR_BIT(direction); /* default: MV_NO_MOVING => MV_DOWN */
5340 return element_info[element].direction_crumbled[action][direction];
5343 int el_act2img(int element, int action)
5345 element = GFX_ELEMENT(element);
5347 return element_info[element].graphic[action];
5350 int el_act2crm(int element, int action)
5352 element = GFX_ELEMENT(element);
5354 return element_info[element].crumbled[action];
5357 int el_dir2img(int element, int direction)
5359 element = GFX_ELEMENT(element);
5361 return el_act_dir2img(element, ACTION_DEFAULT, direction);
5364 int el2baseimg(int element)
5366 return element_info[element].graphic[ACTION_DEFAULT];
5369 int el2img(int element)
5371 element = GFX_ELEMENT(element);
5373 return element_info[element].graphic[ACTION_DEFAULT];
5376 int el2edimg(int element)
5378 element = GFX_ELEMENT(element);
5380 return element_info[element].special_graphic[GFX_SPECIAL_ARG_EDITOR];
5383 int el2preimg(int element)
5385 element = GFX_ELEMENT(element);
5387 return element_info[element].special_graphic[GFX_SPECIAL_ARG_PREVIEW];
5390 int getGameFrameDelay_EM(int native_em_game_frame_delay)
5392 return (GameFrameDelay == GAME_FRAME_DELAY ? native_em_game_frame_delay :
5396 unsigned int InitRND(long seed)
5398 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
5399 return InitEngineRND_EM(seed);
5401 return InitEngineRND(seed);
5404 void InitGraphicInfo_EM(void)
5406 int mapping_EM_to_RND_element[TILE_MAX];
5407 int mapping_EM_to_RND_action[TILE_MAX];
5408 int mapping_EM_to_RND_direction[TILE_MAX];
5409 boolean mapping_EM_to_RND_backside[TILE_MAX];
5412 /* return "EL_UNKNOWN" for all undefined elements in mapping array */
5413 for (i = 0; i < TILE_MAX; i++)
5415 mapping_EM_to_RND_element[i] = EL_UNKNOWN;
5416 mapping_EM_to_RND_backside[i] = FALSE;
5417 mapping_EM_to_RND_action[i] = ACTION_DEFAULT;
5418 mapping_EM_to_RND_direction[i] = MV_NO_MOVING;
5421 for (i = 0; mapping_EM_to_RND_list[i].element_em != -1; i++)
5423 int e = mapping_EM_to_RND_list[i].element_em;
5425 mapping_EM_to_RND_element[e] = mapping_EM_to_RND_list[i].element_rnd;
5426 mapping_EM_to_RND_backside[e] = mapping_EM_to_RND_list[i].is_backside;
5428 if (mapping_EM_to_RND_list[i].action != -1)
5429 mapping_EM_to_RND_action[e] = mapping_EM_to_RND_list[i].action;
5431 if (mapping_EM_to_RND_list[i].direction != -1)
5432 mapping_EM_to_RND_direction[e] = 1<< mapping_EM_to_RND_list[i].direction;
5435 for (i = 0; i < TILE_MAX; i++)
5437 int element = mapping_EM_to_RND_element[i];
5438 int action = mapping_EM_to_RND_action[i];
5439 int direction = mapping_EM_to_RND_direction[i];
5440 int backside = mapping_EM_to_RND_backside[i];
5441 boolean action_removing = (action == ACTION_DIGGING ||
5442 action == ACTION_SNAPPING ||
5443 action == ACTION_COLLECTING);
5444 boolean action_exploding = ((action == ACTION_EXPLODING ||
5445 action == ACTION_SMASHED_BY_ROCK ||
5446 action == ACTION_SMASHED_BY_SPRING) &&
5447 element != EL_DIAMOND);
5448 boolean action_active = (action == ACTION_ACTIVE);
5449 boolean action_other = (action == ACTION_OTHER);
5451 for (j = 0; j < 8; j++)
5453 int effective_element = (j < 7 ? element :
5454 i == Ynut_sB ? element :
5455 i == Xdrip_stretch ? element :
5456 i == Xdrip_stretchB ? element :
5457 i == Ydrip_s1 ? element :
5458 i == Ydrip_s1B ? element :
5459 i == Xball_1B ? element :
5460 i == Xball_2 ? element :
5461 i == Xball_2B ? element :
5462 i == Yball_eat ? element :
5463 i == Yspring_kill_e ? EL_SPRING :
5464 i == Yspring_kill_w ? EL_SPRING :
5465 i == Yemerald_stone ? EL_EMERALD :
5466 i == Ydiamond_stone ? EL_ROCK :
5467 backside ? EL_EMPTY :
5468 action_removing ? EL_EMPTY :
5470 int effective_action = (j < 7 ? action :
5471 i == Ynut_sB ? action :
5472 i == Xdrip_stretch ? action :
5473 i == Xdrip_stretchB ? action :
5474 i == Ydrip_s1 ? action :
5475 i == Ydrip_s1B ? action :
5476 i == Xball_1B ? action :
5477 i == Xball_2 ? action :
5478 i == Xball_2B ? action :
5479 i == Yball_eat ? action :
5480 i == Xsand_stonein_1 ? action :
5481 i == Xsand_stonein_2 ? action :
5482 i == Xsand_stonein_3 ? action :
5483 i == Xsand_stonein_4 ? action :
5484 i == Xsand_stoneout_1 ? action :
5485 i == Xsand_stoneout_2 ? action :
5486 i == Xboom_android ? ACTION_EXPLODING :
5487 action_exploding ? ACTION_EXPLODING :
5488 action_active ? action :
5489 action_other ? action :
5491 int graphic = (direction == MV_NO_MOVING ?
5492 el_act2img(effective_element, effective_action) :
5493 el_act_dir2img(effective_element, effective_action,
5495 struct GraphicInfo *g = &graphic_info[graphic];
5496 struct GraphicInfo_EM *g_em = &graphic_info_em[i][7 - j];
5499 int sync_frame = (i == Xdrip_stretch ? 7 :
5500 i == Xdrip_stretchB ? 7 :
5501 i == Ydrip_s2 ? j + 8 :
5502 i == Ydrip_s2B ? j + 8 :
5512 i == Xball_2B ? j + 8 :
5513 i == Yball_eat ? j + 1 :
5514 i == Xamoeba_1 ? 0 :
5515 i == Xamoeba_2 ? 1 :
5516 i == Xamoeba_3 ? 2 :
5517 i == Xamoeba_4 ? 3 :
5518 i == Xamoeba_5 ? 0 :
5519 i == Xamoeba_6 ? 1 :
5520 i == Xamoeba_7 ? 2 :
5521 i == Xamoeba_8 ? 3 :
5522 i == Xexit_2 ? j + 8 :
5523 i == Xexit_3 ? j + 16 :
5524 i == Xdynamite_1 ? 0 :
5525 i == Xdynamite_2 ? 2 :
5526 i == Xdynamite_3 ? 4 :
5527 i == Xdynamite_4 ? 6 :
5528 i == Xsand_stonein_1 ? j + 1 :
5529 i == Xsand_stonein_2 ? j + 9 :
5530 i == Xsand_stonein_3 ? j + 17 :
5531 i == Xsand_stonein_4 ? j + 25 :
5532 i == Xsand_stoneout_1 && j == 0 ? 1 :
5533 i == Xsand_stoneout_1 && j == 1 ? 1 :
5534 i == Xsand_stoneout_1 && j == 2 ? 2 :
5535 i == Xsand_stoneout_1 && j == 3 ? 4 :
5536 i == Xsand_stoneout_1 && j == 4 ? 4 :
5537 i == Xsand_stoneout_1 && j == 5 ? 6 :
5538 i == Xsand_stoneout_1 && j == 6 ? 8 :
5539 i == Xsand_stoneout_1 && j == 7 ? 8 :
5540 i == Xsand_stoneout_2 && j == 0 ? 10 :
5541 i == Xsand_stoneout_2 && j == 1 ? 12 :
5542 i == Xsand_stoneout_2 && j == 2 ? 14 :
5543 i == Xsand_stoneout_2 && j == 3 ? 16 :
5544 i == Xsand_stoneout_2 && j == 4 ? 18 :
5545 i == Xsand_stoneout_2 && j == 5 ? 22 :
5546 i == Xsand_stoneout_2 && j == 6 ? 26 :
5547 i == Xsand_stoneout_2 && j == 7 ? 30 :
5548 i == Xboom_bug && j == 2 ? 1 :
5549 i == Xboom_bug && j == 3 ? 2 :
5550 i == Xboom_bug && j == 4 ? 2 :
5551 i == Xboom_bug && j == 5 ? 1 :
5552 i == Xboom_bug && j == 6 ? 1 :
5553 i == Xboom_bug && j == 7 ? 0 :
5554 i == Xboom_bomb && j == 2 ? 1 :
5555 i == Xboom_bomb && j == 3 ? 2 :
5556 i == Xboom_bomb && j == 4 ? 2 :
5557 i == Xboom_bomb && j == 5 ? 1 :
5558 i == Xboom_bomb && j == 6 ? 1 :
5559 i == Xboom_bomb && j == 7 ? 0 :
5560 i == Xboom_android && j == 7 ? 3 :
5561 i == Xboom_1 && j == 2 ? 1 :
5562 i == Xboom_1 && j == 3 ? 2 :
5563 i == Xboom_1 && j == 4 ? 2 :
5564 i == Xboom_1 && j == 5 ? 3 :
5565 i == Xboom_1 && j == 6 ? 3 :
5566 i == Xboom_1 && j == 7 ? 4 :
5567 i == Xboom_2 && j == 0 ? 4 :
5568 i == Xboom_2 && j == 1 ? 4 :
5569 i == Xboom_2 && j == 2 ? 5 :
5570 i == Xboom_2 && j == 3 ? 5 :
5571 i == Xboom_2 && j == 4 ? 5 :
5572 i == Xboom_2 && j == 5 ? 6 :
5573 effective_action != action ? 0 :
5576 Bitmap *debug_bitmap = g_em->bitmap;
5577 int debug_src_x = g_em->src_x;
5578 int debug_src_y = g_em->src_y;
5581 int frame = getAnimationFrame(g->anim_frames,
5584 g->anim_start_frame,
5587 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y,
5588 g->double_movement && backside);
5591 g_em->bitmap = src_bitmap;
5592 g_em->src_x = src_x;
5593 g_em->src_y = src_y;
5594 g_em->src_offset_x = 0;
5595 g_em->src_offset_y = 0;
5596 g_em->dst_offset_x = 0;
5597 g_em->dst_offset_y = 0;
5598 g_em->width = TILEX;
5599 g_em->height = TILEY;
5603 if (!g->double_movement && (effective_action == ACTION_FALLING ||
5604 effective_action == ACTION_MOVING ||
5605 effective_action == ACTION_PUSHING))
5608 (effective_action == ACTION_FALLING ? MV_DOWN : direction);
5609 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? 1 : 0);
5610 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? 1 : 0);
5611 int cx = ABS(dx) * TILEX / 8;
5612 int cy = ABS(dy) * TILEY / 8;
5614 if (backside) /* tile where movement starts */
5616 if (dx < 0 || dy < 0)
5618 g_em->src_offset_x = cx * (j + 1);
5619 g_em->src_offset_y = cy * (j + 1);
5623 g_em->dst_offset_x = cx * (j + 1);
5624 g_em->dst_offset_y = cy * (j + 1);
5627 g_em->width = TILEX - cx * (j + 1);
5628 g_em->height = TILEY - cy * (j + 1);
5630 else /* tile where movement ends */
5632 if (dx < 0 || dy < 0)
5634 g_em->dst_offset_x = cx * (7 - j);
5635 g_em->dst_offset_y = cy * (7 - j);
5639 g_em->src_offset_x = cx * (7 - j);
5640 g_em->src_offset_y = cy * (7 - j);
5643 g_em->width = TILEX - cx * (7 - j);
5644 g_em->height = TILEY - cy * (7 - j);
5650 if (g_em->bitmap != debug_bitmap ||
5651 g_em->src_x != debug_src_x ||
5652 g_em->src_y != debug_src_y ||
5653 g_em->src_offset_x != 0 ||
5654 g_em->src_offset_y != 0 ||
5655 g_em->dst_offset_x != 0 ||
5656 g_em->dst_offset_y != 0 ||
5657 g_em->width != TILEX ||
5658 g_em->height != TILEY)
5660 static int last_i = -1;
5669 printf("::: EMC GFX ERROR for element %d -> %d ('%s')",
5670 i, element, element_info[element].token_name);
5672 if (element != effective_element)
5673 printf(" [%d ('%s')]",
5674 effective_element,element_info[effective_element].token_name);
5678 if (g_em->bitmap != debug_bitmap)
5679 printf(" %d(%d): different bitmap!\n",
5682 if (g_em->src_x != debug_src_x ||
5683 g_em->src_y != debug_src_y)
5684 printf(" frame %d (%c): %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
5685 j, (backside ? 'B' : 'F'),
5686 g_em->src_x, g_em->src_y,
5687 g_em->src_x / 32, g_em->src_y / 32,
5688 debug_src_x, debug_src_y,
5689 debug_src_x / 32, debug_src_y / 32);
5691 if (g_em->src_offset_x != 0 ||
5692 g_em->src_offset_y != 0 ||
5693 g_em->dst_offset_x != 0 ||
5694 g_em->dst_offset_y != 0)
5695 printf(" %d(%d): offsets %d,%d and %d,%d should be all 0\n",
5697 g_em->src_offset_x, g_em->src_offset_y,
5698 g_em->dst_offset_x, g_em->dst_offset_y);
5700 if (g_em->width != TILEX ||
5701 g_em->height != TILEY)
5702 printf(" %d(%d): size %d,%d should be %d,%d\n",
5704 g_em->width, g_em->height, TILEX, TILEY);