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 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
729 dst_x = FX + x * TILEX + dx;
730 dst_y = FY + y * TILEY + dy;
732 if (mask_mode == USE_MASKING)
734 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
735 dst_x - src_x, dst_y - src_y);
736 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
740 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
746 inline static void DrawGraphicShiftedDouble(int x, int y, int dx, int dy,
747 int graphic, int frame,
748 int cut_mode, int mask_mode)
753 int width = TILEX, height = TILEY;
756 int x2 = x + SIGN(dx);
757 int y2 = y + SIGN(dy);
758 int anim_frames = graphic_info[graphic].anim_frames;
759 int sync_frame = (dx ? ABS(dx) : ABS(dy)) * anim_frames / TILESIZE;
761 /* re-calculate animation frame for two-tile movement animation */
762 frame = getGraphicAnimationFrame(graphic, sync_frame);
764 if (IN_SCR_FIELD(x1, y1)) /* movement start graphic inside screen area */
766 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, TRUE);
768 dst_x = FX + x1 * TILEX;
769 dst_y = FY + y1 * TILEY;
771 if (mask_mode == USE_MASKING)
773 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
774 dst_x - src_x, dst_y - src_y);
775 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
779 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
782 MarkTileDirty(x1, y1);
785 if (IN_SCR_FIELD(x2, y2)) /* movement end graphic inside screen area */
787 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, FALSE);
789 dst_x = FX + x2 * TILEX;
790 dst_y = FY + y2 * TILEY;
792 if (mask_mode == USE_MASKING)
794 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
795 dst_x - src_x, dst_y - src_y);
796 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
800 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
803 MarkTileDirty(x2, y2);
807 static void DrawGraphicShifted(int x, int y, int dx, int dy,
808 int graphic, int frame,
809 int cut_mode, int mask_mode)
813 DrawGraphic(x, y, graphic, frame);
818 if (graphic_info[graphic].double_movement) /* EM style movement images */
819 DrawGraphicShiftedDouble(x, y, dx, dy, graphic, frame, cut_mode,mask_mode);
821 DrawGraphicShiftedNormal(x, y, dx, dy, graphic, frame, cut_mode,mask_mode);
824 void DrawGraphicShiftedThruMask(int x, int y, int dx, int dy, int graphic,
825 int frame, int cut_mode)
827 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, USE_MASKING);
830 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
831 int cut_mode, int mask_mode)
833 int lx = LEVELX(x), ly = LEVELY(y);
837 if (IN_LEV_FIELD(lx, ly))
839 SetRandomAnimationValue(lx, ly);
841 graphic = el_act_dir2img(element, GfxAction[lx][ly], GfxDir[lx][ly]);
842 frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
844 /* do not use double (EM style) movement graphic when not moving */
845 if (graphic_info[graphic].double_movement && !dx && !dy)
847 graphic = el_act_dir2img(element, ACTION_DEFAULT, GfxDir[lx][ly]);
848 frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
851 else /* border element */
853 graphic = el2img(element);
854 frame = getGraphicAnimationFrame(graphic, -1);
857 if (element == EL_EXPANDABLE_WALL)
859 boolean left_stopped = FALSE, right_stopped = FALSE;
861 if (!IN_LEV_FIELD(lx - 1, ly) || IS_WALL(Feld[lx - 1][ly]))
863 if (!IN_LEV_FIELD(lx + 1, ly) || IS_WALL(Feld[lx + 1][ly]))
864 right_stopped = TRUE;
866 if (left_stopped && right_stopped)
868 else if (left_stopped)
870 graphic = IMG_EXPANDABLE_WALL_GROWING_RIGHT;
871 frame = graphic_info[graphic].anim_frames - 1;
873 else if (right_stopped)
875 graphic = IMG_EXPANDABLE_WALL_GROWING_LEFT;
876 frame = graphic_info[graphic].anim_frames - 1;
881 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
882 else if (mask_mode == USE_MASKING)
883 DrawGraphicThruMask(x, y, graphic, frame);
885 DrawGraphic(x, y, graphic, frame);
888 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
889 int cut_mode, int mask_mode)
891 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
892 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
893 cut_mode, mask_mode);
896 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
899 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
902 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
905 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
908 void DrawLevelElementThruMask(int x, int y, int element)
910 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
913 void DrawLevelFieldThruMask(int x, int y)
915 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
918 #define TILE_GFX_ELEMENT(x, y) \
919 (GfxElement[x][y] != EL_UNDEFINED && Feld[x][y] != EL_EXPLOSION ? \
920 GfxElement[x][y] : Feld[x][y])
922 static void DrawLevelFieldCrumbledSandExt(int x, int y, int graphic, int frame)
926 int sx = SCREENX(x), sy = SCREENY(y);
928 int width, height, cx, cy, i;
930 int crumbled_border_size = graphic_info[graphic].border_size;
932 int snip = TILEX / 8; /* number of border pixels from "crumbled graphic" */
934 static int xy[4][2] =
943 if (x == 0 && y == 7)
944 printf("::: %d, %d [%d]\n", GfxElement[x][y], Feld[x][y],
945 crumbled_border_size);
948 if (!IN_LEV_FIELD(x, y))
951 element = TILE_GFX_ELEMENT(x, y);
953 /* crumble field itself */
954 if (GFX_CRUMBLED(element) && !IS_MOVING(x, y))
956 if (!IN_SCR_FIELD(sx, sy))
959 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
961 for (i = 0; i < 4; i++)
963 int xx = x + xy[i][0];
964 int yy = y + xy[i][1];
967 element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
970 element = (IN_LEV_FIELD(xx, yy) ? Feld[xx][yy] : BorderElement);
973 /* check if neighbour field is of same type */
974 if (GFX_CRUMBLED(element) && !IS_MOVING(xx, yy))
978 if (Feld[x][y] == EL_CUSTOM_START + 123)
979 printf("::: crumble [%d] THE CHAOS ENGINE (%d, %d): %d, %d\n",
980 i, Feld[x][y], element,
981 GFX_CRUMBLED(element), IS_MOVING(x, y));
984 if (i == 1 || i == 2)
986 width = crumbled_border_size;
988 cx = (i == 2 ? TILEX - crumbled_border_size : 0);
994 height = crumbled_border_size;
996 cy = (i == 3 ? TILEY - crumbled_border_size : 0);
999 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1000 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
1003 MarkTileDirty(sx, sy);
1005 else /* crumble neighbour fields */
1008 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1011 for (i = 0; i < 4; i++)
1013 int xx = x + xy[i][0];
1014 int yy = y + xy[i][1];
1015 int sxx = sx + xy[i][0];
1016 int syy = sy + xy[i][1];
1019 if (!IN_LEV_FIELD(xx, yy) ||
1020 !IN_SCR_FIELD(sxx, syy) ||
1024 element = TILE_GFX_ELEMENT(xx, yy);
1026 if (!GFX_CRUMBLED(element))
1029 if (!IN_LEV_FIELD(xx, yy) ||
1030 !IN_SCR_FIELD(sxx, syy) ||
1031 !GFX_CRUMBLED(Feld[xx][yy]) ||
1037 graphic = el_act2crm(Feld[xx][yy], ACTION_DEFAULT);
1038 crumbled_border_size = graphic_info[graphic].border_size;
1040 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1043 if (i == 1 || i == 2)
1045 width = crumbled_border_size;
1047 cx = (i == 1 ? TILEX - crumbled_border_size : 0);
1053 height = crumbled_border_size;
1055 cy = (i == 0 ? TILEY - crumbled_border_size : 0);
1058 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1059 width, height, FX + sxx * TILEX + cx, FY + syy * TILEY + cy);
1061 MarkTileDirty(sxx, syy);
1066 void DrawLevelFieldCrumbledSand(int x, int y)
1071 if (!IN_LEV_FIELD(x, y))
1074 graphic = el_act2crm(Feld[x][y], ACTION_DEFAULT);
1076 DrawLevelFieldCrumbledSandExt(x, y, graphic, 0);
1078 DrawLevelFieldCrumbledSandExt(x, y, IMG_SAND_CRUMBLED, 0);
1082 void DrawLevelFieldCrumbledSandDigging(int x, int y, int direction,
1086 int graphic1 = el_act_dir2img(GfxElement[x][y], ACTION_DIGGING, direction);
1087 int graphic2 = el_act_dir2crm(GfxElement[x][y], ACTION_DIGGING, direction);
1089 int graphic1 = el_act_dir2img(EL_SAND, ACTION_DIGGING, direction);
1090 int graphic2 = el_act_dir2img(EL_SAND_CRUMBLED, ACTION_DIGGING, direction);
1092 int frame1 = getGraphicAnimationFrame(graphic1, step_frame);
1093 int frame2 = getGraphicAnimationFrame(graphic2, step_frame);
1094 int sx = SCREENX(x), sy = SCREENY(y);
1096 DrawGraphic(sx, sy, graphic1, frame1);
1097 DrawLevelFieldCrumbledSandExt(x, y, graphic2, frame2);
1100 void DrawLevelFieldCrumbledSandNeighbours(int x, int y)
1102 int sx = SCREENX(x), sy = SCREENY(y);
1103 static int xy[4][2] =
1112 for (i = 0; i < 4; i++)
1114 int xx = x + xy[i][0];
1115 int yy = y + xy[i][1];
1116 int sxx = sx + xy[i][0];
1117 int syy = sy + xy[i][1];
1119 if (!IN_LEV_FIELD(xx, yy) ||
1120 !IN_SCR_FIELD(sxx, syy) ||
1121 !GFX_CRUMBLED(Feld[xx][yy]) ||
1125 DrawLevelField(xx, yy);
1129 static int getBorderElement(int x, int y)
1133 { EL_STEELWALL_TOPLEFT, EL_INVISIBLE_STEELWALL_TOPLEFT },
1134 { EL_STEELWALL_TOPRIGHT, EL_INVISIBLE_STEELWALL_TOPRIGHT },
1135 { EL_STEELWALL_BOTTOMLEFT, EL_INVISIBLE_STEELWALL_BOTTOMLEFT },
1136 { EL_STEELWALL_BOTTOMRIGHT, EL_INVISIBLE_STEELWALL_BOTTOMRIGHT },
1137 { EL_STEELWALL_VERTICAL, EL_INVISIBLE_STEELWALL_VERTICAL },
1138 { EL_STEELWALL_HORIZONTAL, EL_INVISIBLE_STEELWALL_HORIZONTAL },
1139 { EL_STEELWALL, EL_INVISIBLE_STEELWALL }
1141 int steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
1142 int steel_position = (x == -1 && y == -1 ? 0 :
1143 x == lev_fieldx && y == -1 ? 1 :
1144 x == -1 && y == lev_fieldy ? 2 :
1145 x == lev_fieldx && y == lev_fieldy ? 3 :
1146 x == -1 || x == lev_fieldx ? 4 :
1147 y == -1 || y == lev_fieldy ? 5 : 6);
1149 return border[steel_position][steel_type];
1152 void DrawScreenElement(int x, int y, int element)
1154 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1155 DrawLevelFieldCrumbledSand(LEVELX(x), LEVELY(y));
1158 void DrawLevelElement(int x, int y, int element)
1160 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1161 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1164 void DrawScreenField(int x, int y)
1166 int lx = LEVELX(x), ly = LEVELY(y);
1167 int element, content;
1169 if (!IN_LEV_FIELD(lx, ly))
1171 if (lx < -1 || lx > lev_fieldx || ly < -1 || ly > lev_fieldy)
1174 element = getBorderElement(lx, ly);
1176 DrawScreenElement(x, y, element);
1180 element = Feld[lx][ly];
1181 content = Store[lx][ly];
1183 if (IS_MOVING(lx, ly))
1185 int horiz_move = (MovDir[lx][ly] == MV_LEFT || MovDir[lx][ly] == MV_RIGHT);
1186 boolean cut_mode = NO_CUTTING;
1188 if (element == EL_QUICKSAND_EMPTYING ||
1189 element == EL_MAGIC_WALL_EMPTYING ||
1190 element == EL_BD_MAGIC_WALL_EMPTYING ||
1191 element == EL_AMOEBA_DROPPING)
1192 cut_mode = CUT_ABOVE;
1193 else if (element == EL_QUICKSAND_FILLING ||
1194 element == EL_MAGIC_WALL_FILLING ||
1195 element == EL_BD_MAGIC_WALL_FILLING)
1196 cut_mode = CUT_BELOW;
1198 if (cut_mode == CUT_ABOVE)
1199 DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1201 DrawScreenElement(x, y, EL_EMPTY);
1204 DrawScreenElementShifted(x, y, MovPos[lx][ly], 0, element, NO_CUTTING);
1205 else if (cut_mode == NO_CUTTING)
1206 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], element, cut_mode);
1208 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], content, cut_mode);
1210 if (content == EL_ACID)
1212 int dir = MovDir[lx][ly];
1213 int newlx = lx + (dir == MV_LEFT ? -1 : dir == MV_RIGHT ? +1 : 0);
1214 int newly = ly + (dir == MV_UP ? -1 : dir == MV_DOWN ? +1 : 0);
1216 DrawLevelElementThruMask(newlx, newly, EL_ACID);
1219 else if (IS_BLOCKED(lx, ly))
1224 boolean cut_mode = NO_CUTTING;
1225 int element_old, content_old;
1227 Blocked2Moving(lx, ly, &oldx, &oldy);
1230 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1231 MovDir[oldx][oldy] == MV_RIGHT);
1233 element_old = Feld[oldx][oldy];
1234 content_old = Store[oldx][oldy];
1236 if (element_old == EL_QUICKSAND_EMPTYING ||
1237 element_old == EL_MAGIC_WALL_EMPTYING ||
1238 element_old == EL_BD_MAGIC_WALL_EMPTYING ||
1239 element_old == EL_AMOEBA_DROPPING)
1240 cut_mode = CUT_ABOVE;
1242 DrawScreenElement(x, y, EL_EMPTY);
1245 DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
1247 else if (cut_mode == NO_CUTTING)
1248 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
1251 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
1254 else if (IS_DRAWABLE(element))
1255 DrawScreenElement(x, y, element);
1257 DrawScreenElement(x, y, EL_EMPTY);
1260 void DrawLevelField(int x, int y)
1262 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1263 DrawScreenField(SCREENX(x), SCREENY(y));
1264 else if (IS_MOVING(x, y))
1268 Moving2Blocked(x, y, &newx, &newy);
1269 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1270 DrawScreenField(SCREENX(newx), SCREENY(newy));
1272 else if (IS_BLOCKED(x, y))
1276 Blocked2Moving(x, y, &oldx, &oldy);
1277 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1278 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1282 void DrawMiniElement(int x, int y, int element)
1286 graphic = el2edimg(element);
1287 DrawMiniGraphic(x, y, graphic);
1290 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1292 int x = sx + scroll_x, y = sy + scroll_y;
1294 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1295 DrawMiniElement(sx, sy, EL_EMPTY);
1296 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1297 DrawMiniElement(sx, sy, Feld[x][y]);
1299 DrawMiniGraphic(sx, sy, el2edimg(getBorderElement(x, y)));
1302 void DrawEnvelopeBackground(int envelope_nr, int startx, int starty,
1303 int x, int y, int xsize, int ysize, int font_nr)
1305 int font_width = getFontWidth(font_nr);
1306 int font_height = getFontHeight(font_nr);
1307 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1310 int dst_x = SX + startx + x * font_width;
1311 int dst_y = SY + starty + y * font_height;
1312 int width = graphic_info[graphic].width;
1313 int height = graphic_info[graphic].height;
1314 int inner_width = MAX(width - 2 * font_width, font_width);
1315 int inner_height = MAX(height - 2 * font_height, font_height);
1316 int inner_sx = (width >= 3 * font_width ? font_width : 0);
1317 int inner_sy = (height >= 3 * font_height ? font_height : 0);
1318 boolean draw_masked = graphic_info[graphic].draw_masked;
1320 getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
1322 if (src_bitmap == NULL || width < font_width || height < font_height)
1324 ClearRectangle(drawto, dst_x, dst_y, font_width, font_height);
1328 src_x += (x == 0 ? 0 : x == xsize - 1 ? width - font_width :
1329 inner_sx + (x - 1) * font_width % inner_width);
1330 src_y += (y == 0 ? 0 : y == ysize - 1 ? height - font_height :
1331 inner_sy + (y - 1) * font_height % inner_height);
1335 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1336 dst_x - src_x, dst_y - src_y);
1337 BlitBitmapMasked(src_bitmap, drawto, src_x, src_y, font_width, font_height,
1341 BlitBitmap(src_bitmap, drawto, src_x, src_y, font_width, font_height,
1345 void AnimateEnvelope(int envelope_nr, int anim_mode, int action)
1347 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1349 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
1350 int mask_mode = (src_bitmap != NULL ? BLIT_MASKED : BLIT_ON_BACKGROUND);
1352 boolean draw_masked = graphic_info[graphic].draw_masked;
1353 int mask_mode = (draw_masked ? BLIT_MASKED : BLIT_ON_BACKGROUND);
1355 boolean ffwd_delay = (tape.playing && tape.fast_forward);
1356 boolean no_delay = (tape.warp_forward);
1357 unsigned long anim_delay = 0;
1358 int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
1359 int anim_delay_value = (no_delay ? 0 : frame_delay_value);
1360 int font_nr = FONT_ENVELOPE_1 + envelope_nr;
1361 int font_width = getFontWidth(font_nr);
1362 int font_height = getFontHeight(font_nr);
1363 int max_xsize = level.envelope_xsize[envelope_nr];
1364 int max_ysize = level.envelope_ysize[envelope_nr];
1365 int xstart = (anim_mode & ANIM_VERTICAL ? max_xsize : 0);
1366 int ystart = (anim_mode & ANIM_HORIZONTAL ? max_ysize : 0);
1367 int xend = max_xsize;
1368 int yend = (anim_mode != ANIM_DEFAULT ? max_ysize : 0);
1369 int xstep = (xstart < xend ? 1 : 0);
1370 int ystep = (ystart < yend || xstep == 0 ? 1 : 0);
1373 for (x = xstart, y = ystart; x <= xend && y <= yend; x += xstep, y += ystep)
1375 int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2;
1376 int ysize = (action == ACTION_CLOSING ? yend - (y - ystart) : y) + 2;
1377 int sx = (SXSIZE - xsize * font_width) / 2;
1378 int sy = (SYSIZE - ysize * font_height) / 2;
1381 SetDrawtoField(DRAW_BUFFERED);
1383 BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
1385 SetDrawtoField(DRAW_BACKBUFFER);
1387 for (yy = 0; yy < ysize; yy++) for (xx = 0; xx < xsize; xx++)
1388 DrawEnvelopeBackground(envelope_nr, sx,sy, xx,yy, xsize, ysize, font_nr);
1390 DrawTextToTextArea(SX + sx + font_width, SY + sy + font_height,
1391 level.envelope_text[envelope_nr], font_nr, max_xsize,
1392 xsize - 2, ysize - 2, mask_mode);
1394 redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
1397 WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
1401 void ShowEnvelope(int envelope_nr)
1403 int element = EL_ENVELOPE_1 + envelope_nr;
1404 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1405 int sound_opening = element_info[element].sound[ACTION_OPENING];
1406 int sound_closing = element_info[element].sound[ACTION_CLOSING];
1407 boolean ffwd_delay = (tape.playing && tape.fast_forward);
1408 boolean no_delay = (tape.warp_forward);
1409 int normal_delay_value = ONE_SECOND_DELAY / (ffwd_delay ? 2 : 1);
1410 int wait_delay_value = (no_delay ? 0 : normal_delay_value);
1411 int anim_mode = graphic_info[graphic].anim_mode;
1412 int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL:
1413 anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode);
1415 game.envelope_active = TRUE; /* needed for RedrawPlayfield() events */
1417 PlaySoundStereo(sound_opening, SOUND_MIDDLE);
1419 if (anim_mode == ANIM_DEFAULT)
1420 AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_OPENING);
1422 AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_OPENING);
1425 Delay(wait_delay_value);
1427 WaitForEventToContinue();
1429 PlaySoundStereo(sound_closing, SOUND_MIDDLE);
1431 if (anim_mode != ANIM_NONE)
1432 AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_CLOSING);
1434 if (anim_mode == ANIM_DEFAULT)
1435 AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_CLOSING);
1437 game.envelope_active = FALSE;
1439 SetDrawtoField(DRAW_BUFFERED);
1441 redraw_mask |= REDRAW_FIELD;
1445 void getMicroGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1447 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
1448 int mini_startx = src_bitmap->width * 3 / 4;
1449 int mini_starty = src_bitmap->height * 2 / 3;
1450 int src_x = mini_startx + graphic_info[graphic].src_x / 8;
1451 int src_y = mini_starty + graphic_info[graphic].src_y / 8;
1453 *bitmap = src_bitmap;
1458 void DrawMicroElement(int xpos, int ypos, int element)
1462 int graphic = el2preimg(element);
1464 getMicroGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1465 BlitBitmap(src_bitmap, drawto, src_x, src_y, MICRO_TILEX, MICRO_TILEY,
1473 SetDrawBackgroundMask(REDRAW_NONE);
1476 for (x = BX1; x <= BX2; x++)
1477 for (y = BY1; y <= BY2; y++)
1478 DrawScreenField(x, y);
1480 redraw_mask |= REDRAW_FIELD;
1483 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1487 for (x = 0; x < size_x; x++)
1488 for (y = 0; y < size_y; y++)
1489 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1491 redraw_mask |= REDRAW_FIELD;
1494 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1498 DrawBackground(xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
1500 if (lev_fieldx < STD_LEV_FIELDX)
1501 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1502 if (lev_fieldy < STD_LEV_FIELDY)
1503 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1505 xpos += MICRO_TILEX;
1506 ypos += MICRO_TILEY;
1508 for (x = -1; x <= STD_LEV_FIELDX; x++)
1510 for (y = -1; y <= STD_LEV_FIELDY; y++)
1512 int lx = from_x + x, ly = from_y + y;
1514 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1515 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1516 level.field[lx][ly]);
1517 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1
1518 && BorderElement != EL_EMPTY)
1519 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1520 getBorderElement(lx, ly));
1524 redraw_mask |= REDRAW_MICROLEVEL;
1527 #define MICROLABEL_EMPTY 0
1528 #define MICROLABEL_LEVEL_NAME 1
1529 #define MICROLABEL_CREATED_BY 2
1530 #define MICROLABEL_LEVEL_AUTHOR 3
1531 #define MICROLABEL_IMPORTED_FROM 4
1532 #define MICROLABEL_LEVEL_IMPORT_INFO 5
1534 static void DrawMicroLevelLabelExt(int mode)
1536 char label_text[MAX_OUTPUT_LINESIZE + 1];
1537 int max_len_label_text;
1538 int font_nr = FONT_TEXT_2;
1540 if (mode == MICROLABEL_CREATED_BY || mode == MICROLABEL_IMPORTED_FROM)
1541 font_nr = FONT_TEXT_3;
1543 max_len_label_text = SXSIZE / getFontWidth(font_nr);
1545 DrawBackground(SX, MICROLABEL_YPOS, SXSIZE, getFontHeight(font_nr));
1547 strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
1548 mode == MICROLABEL_CREATED_BY ? "created by" :
1549 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
1550 mode == MICROLABEL_IMPORTED_FROM ? "imported from" :
1551 mode == MICROLABEL_LEVEL_IMPORT_INFO ?
1552 leveldir_current->imported_from : ""),
1553 max_len_label_text);
1554 label_text[max_len_label_text] = '\0';
1556 if (strlen(label_text) > 0)
1558 int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
1559 int lypos = MICROLABEL_YPOS;
1561 DrawText(lxpos, lypos, label_text, font_nr);
1564 redraw_mask |= REDRAW_MICROLEVEL;
1567 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1569 static unsigned long scroll_delay = 0;
1570 static unsigned long label_delay = 0;
1571 static int from_x, from_y, scroll_direction;
1572 static int label_state, label_counter;
1573 int last_game_status = game_status; /* save current game status */
1575 /* force PREVIEW font on preview level */
1576 game_status = GAME_MODE_PSEUDO_PREVIEW;
1580 from_x = from_y = 0;
1581 scroll_direction = MV_RIGHT;
1585 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1586 DrawMicroLevelLabelExt(label_state);
1588 /* initialize delay counters */
1589 DelayReached(&scroll_delay, 0);
1590 DelayReached(&label_delay, 0);
1592 if (leveldir_current->name)
1594 int text_width = getTextWidth(leveldir_current->name, FONT_TEXT_1);
1595 int lxpos = SX + (SXSIZE - text_width) / 2;
1596 int lypos = SY + 352;
1598 DrawText(lxpos, lypos, leveldir_current->name, FONT_TEXT_1);
1601 game_status = last_game_status; /* restore current game status */
1606 /* scroll micro level, if needed */
1607 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1608 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1610 switch (scroll_direction)
1616 scroll_direction = MV_UP;
1620 if (from_x < lev_fieldx - STD_LEV_FIELDX)
1623 scroll_direction = MV_DOWN;
1630 scroll_direction = MV_RIGHT;
1634 if (from_y < lev_fieldy - STD_LEV_FIELDY)
1637 scroll_direction = MV_LEFT;
1644 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1647 /* redraw micro level label, if needed */
1648 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1649 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1650 strcmp(level.author, leveldir_current->name) != 0 &&
1651 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1653 int max_label_counter = 23;
1655 if (leveldir_current->imported_from != NULL)
1656 max_label_counter += 14;
1658 label_counter = (label_counter + 1) % max_label_counter;
1659 label_state = (label_counter >= 0 && label_counter <= 7 ?
1660 MICROLABEL_LEVEL_NAME :
1661 label_counter >= 9 && label_counter <= 12 ?
1662 MICROLABEL_CREATED_BY :
1663 label_counter >= 14 && label_counter <= 21 ?
1664 MICROLABEL_LEVEL_AUTHOR :
1665 label_counter >= 23 && label_counter <= 26 ?
1666 MICROLABEL_IMPORTED_FROM :
1667 label_counter >= 28 && label_counter <= 35 ?
1668 MICROLABEL_LEVEL_IMPORT_INFO : MICROLABEL_EMPTY);
1669 DrawMicroLevelLabelExt(label_state);
1672 game_status = last_game_status; /* restore current game status */
1675 inline void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
1676 int graphic, int sync_frame, int mask_mode)
1678 int frame = getGraphicAnimationFrame(graphic, sync_frame);
1680 if (mask_mode == USE_MASKING)
1681 DrawGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
1683 DrawGraphicExt(dst_bitmap, x, y, graphic, frame);
1686 inline void DrawGraphicAnimation(int x, int y, int graphic)
1688 int lx = LEVELX(x), ly = LEVELY(y);
1690 if (!IN_SCR_FIELD(x, y))
1693 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
1694 graphic, GfxFrame[lx][ly], NO_MASKING);
1695 MarkTileDirty(x, y);
1698 void DrawLevelGraphicAnimation(int x, int y, int graphic)
1700 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
1703 void DrawLevelElementAnimation(int x, int y, int element)
1706 int graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
1708 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
1710 DrawGraphicAnimation(SCREENX(x), SCREENY(y), el2img(element));
1714 inline void DrawLevelGraphicAnimationIfNeeded(int x, int y, int graphic)
1716 int sx = SCREENX(x), sy = SCREENY(y);
1718 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
1721 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
1724 DrawGraphicAnimation(sx, sy, graphic);
1726 if (GFX_CRUMBLED(Feld[x][y]))
1727 DrawLevelFieldCrumbledSand(x, y);
1730 void DrawLevelElementAnimationIfNeeded(int x, int y, int element)
1732 int sx = SCREENX(x), sy = SCREENY(y);
1735 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
1738 graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
1740 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
1743 DrawGraphicAnimation(sx, sy, graphic);
1745 if (GFX_CRUMBLED(element))
1746 DrawLevelFieldCrumbledSand(x, y);
1749 static int getPlayerGraphic(struct PlayerInfo *player, int move_dir)
1751 if (player->use_murphy_graphic)
1753 /* this works only because currently only one player can be "murphy" ... */
1754 static int last_horizontal_dir = MV_LEFT;
1755 int graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, move_dir);
1757 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
1758 last_horizontal_dir = move_dir;
1760 if (graphic == IMG_SP_MURPHY) /* undefined => use special graphic */
1762 int direction = (player->is_snapping ? move_dir : last_horizontal_dir);
1764 graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, direction);
1770 return el_act_dir2img(player->element_nr, player->GfxAction, move_dir);
1773 static boolean equalGraphics(int graphic1, int graphic2)
1775 struct GraphicInfo *g1 = &graphic_info[graphic1];
1776 struct GraphicInfo *g2 = &graphic_info[graphic2];
1778 return (g1->bitmap == g2->bitmap &&
1779 g1->src_x == g2->src_x &&
1780 g1->src_y == g2->src_y &&
1781 g1->anim_frames == g2->anim_frames &&
1782 g1->anim_delay == g2->anim_delay &&
1783 g1->anim_mode == g2->anim_mode);
1786 void DrawAllPlayers()
1790 for (i = 0; i < MAX_PLAYERS; i++)
1791 if (stored_player[i].active)
1792 DrawPlayer(&stored_player[i]);
1795 void DrawPlayerField(int x, int y)
1797 if (!IS_PLAYER(x, y))
1800 DrawPlayer(PLAYERINFO(x, y));
1803 void DrawPlayer(struct PlayerInfo *player)
1805 int jx = player->jx;
1806 int jy = player->jy;
1807 int move_dir = player->MovDir;
1809 int last_jx = player->last_jx;
1810 int last_jy = player->last_jy;
1811 int next_jx = jx + (jx - last_jx);
1812 int next_jy = jy + (jy - last_jy);
1813 boolean player_is_moving = (last_jx != jx || last_jy != jy ? TRUE : FALSE);
1815 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? +1 : 0);
1816 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? +1 : 0);
1817 int last_jx = (player->is_moving ? jx - dx : jx);
1818 int last_jy = (player->is_moving ? jy - dy : jy);
1819 int next_jx = jx + dx;
1820 int next_jy = jy + dy;
1821 boolean player_is_moving = (player->MovPos ? TRUE : FALSE);
1823 int sx = SCREENX(jx), sy = SCREENY(jy);
1824 int sxx = 0, syy = 0;
1825 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
1827 int action = ACTION_DEFAULT;
1828 int last_player_graphic = getPlayerGraphic(player, move_dir);
1829 int last_player_frame = player->Frame;
1832 if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
1836 if (!IN_LEV_FIELD(jx, jy))
1838 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
1839 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
1840 printf("DrawPlayerField(): This should never happen!\n");
1845 if (element == EL_EXPLOSION)
1848 action = (player->is_pushing ? ACTION_PUSHING :
1849 player->is_digging ? ACTION_DIGGING :
1850 player->is_collecting ? ACTION_COLLECTING :
1851 player->is_moving ? ACTION_MOVING :
1852 player->is_snapping ? ACTION_SNAPPING :
1853 player->is_dropping ? ACTION_DROPPING :
1854 player->is_waiting ? player->action_waiting : ACTION_DEFAULT);
1856 InitPlayerGfxAnimation(player, action, move_dir);
1858 /* ----------------------------------------------------------------------- */
1859 /* draw things in the field the player is leaving, if needed */
1860 /* ----------------------------------------------------------------------- */
1863 if (player->is_moving)
1865 if (player_is_moving)
1868 if (Back[last_jx][last_jy] && IS_DRAWABLE(last_element))
1870 DrawLevelElement(last_jx, last_jy, Back[last_jx][last_jy]);
1872 if (last_element == EL_DYNAMITE_ACTIVE ||
1873 last_element == EL_SP_DISK_RED_ACTIVE)
1874 DrawDynamite(last_jx, last_jy);
1876 DrawLevelFieldThruMask(last_jx, last_jy);
1878 else if (last_element == EL_DYNAMITE_ACTIVE ||
1879 last_element == EL_SP_DISK_RED_ACTIVE)
1880 DrawDynamite(last_jx, last_jy);
1882 DrawLevelField(last_jx, last_jy);
1884 if (player->is_pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
1885 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
1888 if (!IN_SCR_FIELD(sx, sy))
1891 if (setup.direct_draw)
1892 SetDrawtoField(DRAW_BUFFERED);
1894 /* ----------------------------------------------------------------------- */
1895 /* draw things behind the player, if needed */
1896 /* ----------------------------------------------------------------------- */
1899 DrawLevelElement(jx, jy, Back[jx][jy]);
1900 else if (IS_ACTIVE_BOMB(element))
1901 DrawLevelElement(jx, jy, EL_EMPTY);
1904 if (player_is_moving && GfxElement[jx][jy] != EL_UNDEFINED)
1906 if (GFX_CRUMBLED(GfxElement[jx][jy]))
1907 DrawLevelFieldCrumbledSandDigging(jx, jy, move_dir, player->StepFrame);
1910 int old_element = GfxElement[jx][jy];
1911 int old_graphic = el_act_dir2img(old_element, action, move_dir);
1912 int frame = getGraphicAnimationFrame(old_graphic, player->StepFrame);
1914 DrawGraphic(sx, sy, old_graphic, frame);
1919 GfxElement[jx][jy] = EL_UNDEFINED;
1921 DrawLevelField(jx, jy);
1925 /* ----------------------------------------------------------------------- */
1926 /* draw player himself */
1927 /* ----------------------------------------------------------------------- */
1931 graphic = getPlayerGraphic(player, move_dir);
1933 /* in the case of changed player action or direction, prevent the current
1934 animation frame from being restarted for identical animations */
1935 if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic))
1936 player->Frame = last_player_frame;
1940 if (player->use_murphy_graphic)
1942 static int last_horizontal_dir = MV_LEFT;
1944 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
1945 last_horizontal_dir = move_dir;
1947 graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, move_dir);
1949 if (graphic == IMG_SP_MURPHY) /* undefined => use special graphic */
1951 int direction = (player->is_snapping ? move_dir : last_horizontal_dir);
1953 graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, direction);
1957 graphic = el_act_dir2img(player->element_nr, player->GfxAction, move_dir);
1961 frame = getGraphicAnimationFrame(graphic, player->Frame);
1965 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
1966 sxx = player->GfxPos;
1968 syy = player->GfxPos;
1971 if (!setup.soft_scrolling && ScreenMovPos)
1974 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
1976 if (SHIELD_ON(player))
1978 int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
1979 IMG_SHIELD_NORMAL_ACTIVE);
1980 int frame = getGraphicAnimationFrame(graphic, -1);
1982 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
1985 /* ----------------------------------------------------------------------- */
1986 /* draw things the player is pushing, if needed */
1987 /* ----------------------------------------------------------------------- */
1990 printf("::: %d, %d [%d, %d] [%d]\n",
1991 player->is_pushing, player_is_moving, player->GfxAction,
1992 player->is_moving, player_is_moving);
1996 if (player->is_pushing && player->is_moving)
1998 if (player->is_pushing && player_is_moving)
2001 int px = SCREENX(next_jx), py = SCREENY(next_jy);
2003 if (Back[next_jx][next_jy])
2004 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
2006 if ((sxx || syy) && element == EL_SOKOBAN_OBJECT)
2007 DrawGraphicShiftedThruMask(px, py, sxx, syy, IMG_SOKOBAN_OBJECT, 0,
2011 int element = MovingOrBlocked2Element(next_jx, next_jy);
2012 int graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
2014 int frame = getGraphicAnimationFrame(graphic, player->StepFrame);
2016 int frame = getGraphicAnimationFrame(graphic, player->Frame);
2019 DrawGraphicShifted(px, py, sxx, syy, graphic, frame,
2020 NO_CUTTING, NO_MASKING);
2024 /* ----------------------------------------------------------------------- */
2025 /* draw things in front of player (active dynamite or dynabombs) */
2026 /* ----------------------------------------------------------------------- */
2028 if (IS_ACTIVE_BOMB(element))
2030 graphic = el2img(element);
2031 frame = getGraphicAnimationFrame(graphic, GfxFrame[jx][jy]);
2033 if (game.emulation == EMU_SUPAPLEX)
2034 DrawGraphic(sx, sy, IMG_SP_DISK_RED, frame);
2036 DrawGraphicThruMask(sx, sy, graphic, frame);
2039 if (player_is_moving && last_element == EL_EXPLOSION)
2041 int graphic = el_act2img(GfxElement[last_jx][last_jy], ACTION_EXPLODING);
2042 int delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2);
2043 int phase = ExplodePhase[last_jx][last_jy] - 1;
2044 int frame = getGraphicAnimationFrame(graphic, phase - delay);
2047 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy), graphic, frame);
2050 /* ----------------------------------------------------------------------- */
2051 /* draw elements the player is just walking/passing through/under */
2052 /* ----------------------------------------------------------------------- */
2054 if (player_is_moving)
2056 /* handle the field the player is leaving ... */
2057 if (IS_ACCESSIBLE_INSIDE(last_element))
2058 DrawLevelField(last_jx, last_jy);
2059 else if (IS_ACCESSIBLE_UNDER(last_element))
2060 DrawLevelFieldThruMask(last_jx, last_jy);
2064 /* do not redraw accessible elements if the player is just pushing them */
2065 if (!player_is_moving || !player->is_pushing)
2067 /* ... and the field the player is entering */
2068 if (IS_ACCESSIBLE_INSIDE(element))
2069 DrawLevelField(jx, jy);
2070 else if (IS_ACCESSIBLE_UNDER(element))
2071 DrawLevelFieldThruMask(jx, jy);
2077 /* !!! I have forgotton what this should be good for !!! */
2078 /* !!! causes player being visible when pushing from within tubes !!! */
2079 if (!player->is_pushing)
2082 /* ... and the field the player is entering */
2083 if (IS_ACCESSIBLE_INSIDE(element))
2084 DrawLevelField(jx, jy);
2085 else if (IS_ACCESSIBLE_UNDER(element))
2086 DrawLevelFieldThruMask(jx, jy);
2090 if (setup.direct_draw)
2092 int dst_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
2093 int dst_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
2094 int x_size = TILEX * (1 + ABS(jx - last_jx));
2095 int y_size = TILEY * (1 + ABS(jy - last_jy));
2097 BlitBitmap(drawto_field, window,
2098 dst_x, dst_y, x_size, y_size, dst_x, dst_y);
2099 SetDrawtoField(DRAW_DIRECT);
2102 MarkTileDirty(sx, sy);
2105 /* ------------------------------------------------------------------------- */
2107 void WaitForEventToContinue()
2109 boolean still_wait = TRUE;
2111 /* simulate releasing mouse button over last gadget, if still pressed */
2113 HandleGadgets(-1, -1, 0);
2115 button_status = MB_RELEASED;
2127 case EVENT_BUTTONPRESS:
2128 case EVENT_KEYPRESS:
2132 case EVENT_KEYRELEASE:
2133 ClearPlayerAction();
2137 HandleOtherEvents(&event);
2141 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2148 /* don't eat all CPU time */
2153 #define MAX_REQUEST_LINES 13
2154 #define MAX_REQUEST_LINE_FONT1_LEN 7
2155 #define MAX_REQUEST_LINE_FONT2_LEN 10
2157 boolean Request(char *text, unsigned int req_state)
2159 int mx, my, ty, result = -1;
2160 unsigned int old_door_state;
2161 int last_game_status = game_status; /* save current game status */
2162 int max_request_line_len = MAX_REQUEST_LINE_FONT1_LEN;
2163 int font_nr = FONT_TEXT_2;
2164 int max_word_len = 0;
2167 for (text_ptr = text; *text_ptr; text_ptr++)
2169 max_word_len = (*text_ptr != ' ' ? max_word_len + 1 : 0);
2171 if (max_word_len > MAX_REQUEST_LINE_FONT1_LEN)
2173 max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
2174 font_nr = FONT_LEVEL_NUMBER;
2181 /* disable deactivated drawing when quick-loading level tape recording */
2182 if (tape.playing && tape.deactivate_display)
2183 TapeDeactivateDisplayOff(TRUE);
2187 SetMouseCursor(CURSOR_DEFAULT);
2190 #if defined(NETWORK_AVALIABLE)
2191 /* pause network game while waiting for request to answer */
2192 if (options.network &&
2193 game_status == GAME_MODE_PLAYING &&
2194 req_state & REQUEST_WAIT_FOR_INPUT)
2195 SendToServer_PausePlaying();
2198 old_door_state = GetDoorState();
2200 /* simulate releasing mouse button over last gadget, if still pressed */
2202 HandleGadgets(-1, -1, 0);
2206 if (old_door_state & DOOR_OPEN_1)
2208 CloseDoor(DOOR_CLOSE_1);
2210 /* save old door content */
2211 BlitBitmap(bitmap_db_door, bitmap_db_door,
2212 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
2213 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
2216 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
2218 /* clear door drawing field */
2219 DrawBackground(DX, DY, DXSIZE, DYSIZE);
2221 /* force DOOR font on preview level */
2222 game_status = GAME_MODE_PSEUDO_DOOR;
2224 /* write text for request */
2225 for (ty = 0; ty < MAX_REQUEST_LINES; ty++)
2227 char text_line[max_request_line_len + 1];
2233 for (tl = 0, tx = 0; tx < max_request_line_len; tl++, tx++)
2236 if (!tc || tc == ' ')
2247 strncpy(text_line, text, tl);
2250 DrawText(DX + (DXSIZE - tl * getFontWidth(font_nr)) / 2,
2251 DY + 8 + ty * (getFontHeight(font_nr) + 2),
2252 text_line, font_nr);
2254 text += tl + (tc == ' ' ? 1 : 0);
2257 game_status = last_game_status; /* restore current game status */
2259 if (req_state & REQ_ASK)
2261 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
2262 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
2264 else if (req_state & REQ_CONFIRM)
2266 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
2268 else if (req_state & REQ_PLAYER)
2270 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
2271 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
2272 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
2273 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
2276 /* copy request gadgets to door backbuffer */
2277 BlitBitmap(drawto, bitmap_db_door,
2278 DX, DY, DXSIZE, DYSIZE,
2279 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2281 OpenDoor(DOOR_OPEN_1);
2287 if (!(req_state & REQUEST_WAIT_FOR_INPUT))
2289 SetDrawBackgroundMask(REDRAW_FIELD);
2294 if (game_status != GAME_MODE_MAIN)
2297 button_status = MB_RELEASED;
2299 request_gadget_id = -1;
2301 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
2304 SetMouseCursor(CURSOR_DEFAULT);
2317 case EVENT_BUTTONPRESS:
2318 case EVENT_BUTTONRELEASE:
2319 case EVENT_MOTIONNOTIFY:
2321 if (event.type == EVENT_MOTIONNOTIFY)
2323 if (!PointerInWindow(window))
2324 continue; /* window and pointer are on different screens */
2329 motion_status = TRUE;
2330 mx = ((MotionEvent *) &event)->x;
2331 my = ((MotionEvent *) &event)->y;
2335 motion_status = FALSE;
2336 mx = ((ButtonEvent *) &event)->x;
2337 my = ((ButtonEvent *) &event)->y;
2338 if (event.type == EVENT_BUTTONPRESS)
2339 button_status = ((ButtonEvent *) &event)->button;
2341 button_status = MB_RELEASED;
2344 /* this sets 'request_gadget_id' */
2345 HandleGadgets(mx, my, button_status);
2347 switch(request_gadget_id)
2349 case TOOL_CTRL_ID_YES:
2352 case TOOL_CTRL_ID_NO:
2355 case TOOL_CTRL_ID_CONFIRM:
2356 result = TRUE | FALSE;
2359 case TOOL_CTRL_ID_PLAYER_1:
2362 case TOOL_CTRL_ID_PLAYER_2:
2365 case TOOL_CTRL_ID_PLAYER_3:
2368 case TOOL_CTRL_ID_PLAYER_4:
2379 case EVENT_KEYPRESS:
2380 switch(GetEventKey((KeyEvent *)&event, TRUE))
2393 if (req_state & REQ_PLAYER)
2397 case EVENT_KEYRELEASE:
2398 ClearPlayerAction();
2402 HandleOtherEvents(&event);
2406 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2408 int joy = AnyJoystick();
2410 if (joy & JOY_BUTTON_1)
2412 else if (joy & JOY_BUTTON_2)
2418 /* don't eat all CPU time */
2422 if (game_status != GAME_MODE_MAIN)
2427 if (!(req_state & REQ_STAY_OPEN))
2429 CloseDoor(DOOR_CLOSE_1);
2431 if (((old_door_state & DOOR_OPEN_1) && !(req_state & REQ_STAY_CLOSED)) ||
2432 (req_state & REQ_REOPEN))
2433 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
2438 SetDrawBackgroundMask(REDRAW_FIELD);
2440 #if defined(NETWORK_AVALIABLE)
2441 /* continue network game after request */
2442 if (options.network &&
2443 game_status == GAME_MODE_PLAYING &&
2444 req_state & REQUEST_WAIT_FOR_INPUT)
2445 SendToServer_ContinuePlaying();
2449 /* restore deactivated drawing when quick-loading level tape recording */
2450 if (tape.playing && tape.deactivate_display)
2451 TapeDeactivateDisplayOn();
2457 unsigned int OpenDoor(unsigned int door_state)
2459 if (door_state & DOOR_COPY_BACK)
2461 if (door_state & DOOR_OPEN_1)
2462 BlitBitmap(bitmap_db_door, bitmap_db_door,
2463 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
2464 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2466 if (door_state & DOOR_OPEN_2)
2467 BlitBitmap(bitmap_db_door, bitmap_db_door,
2468 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY2, VXSIZE, VYSIZE,
2469 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2471 door_state &= ~DOOR_COPY_BACK;
2474 return MoveDoor(door_state);
2477 unsigned int CloseDoor(unsigned int door_state)
2479 unsigned int old_door_state = GetDoorState();
2481 if (!(door_state & DOOR_NO_COPY_BACK))
2483 if (old_door_state & DOOR_OPEN_1)
2484 BlitBitmap(backbuffer, bitmap_db_door,
2485 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2487 if (old_door_state & DOOR_OPEN_2)
2488 BlitBitmap(backbuffer, bitmap_db_door,
2489 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2491 door_state &= ~DOOR_NO_COPY_BACK;
2494 return MoveDoor(door_state);
2497 unsigned int GetDoorState()
2499 return MoveDoor(DOOR_GET_STATE);
2502 unsigned int SetDoorState(unsigned int door_state)
2504 return MoveDoor(door_state | DOOR_SET_STATE);
2507 unsigned int MoveDoor(unsigned int door_state)
2509 static int door1 = DOOR_OPEN_1;
2510 static int door2 = DOOR_CLOSE_2;
2511 unsigned long door_delay = 0;
2512 unsigned long door_delay_value;
2515 if (door_state == DOOR_GET_STATE)
2516 return(door1 | door2);
2518 if (door_state & DOOR_SET_STATE)
2520 if (door_state & DOOR_ACTION_1)
2521 door1 = door_state & DOOR_ACTION_1;
2522 if (door_state & DOOR_ACTION_2)
2523 door2 = door_state & DOOR_ACTION_2;
2525 return(door1 | door2);
2528 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2529 door_state &= ~DOOR_OPEN_1;
2530 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2531 door_state &= ~DOOR_CLOSE_1;
2532 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2533 door_state &= ~DOOR_OPEN_2;
2534 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2535 door_state &= ~DOOR_CLOSE_2;
2537 door_delay_value = (door_state & DOOR_ACTION_1 ? door_1.step_delay :
2540 if (setup.quick_doors)
2542 stepsize = 20; /* must be choosen to always draw last frame */
2543 door_delay_value = 0;
2546 StopSound(SND_DOOR_OPENING);
2547 StopSound(SND_DOOR_CLOSING);
2551 if (global.autoplay_leveldir)
2553 door_state |= DOOR_NO_DELAY;
2554 door_state &= ~DOOR_CLOSE_ALL;
2557 if (door_state & DOOR_ACTION)
2559 boolean door_1_done = !(door_state & DOOR_ACTION_1);
2560 boolean door_2_done = !(door_state & DOOR_ACTION_2);
2561 int start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2562 int end = (door_state & DOOR_ACTION_1 &&
2563 door_1.anim_mode == ANIM_VERTICAL ? DYSIZE : DXSIZE);
2566 if (!(door_state & DOOR_NO_DELAY) && !setup.quick_doors)
2568 /* opening door sound has priority over simultaneously closing door */
2569 if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
2570 PlaySoundStereo(SND_DOOR_OPENING, SOUND_MIDDLE);
2571 else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
2572 PlaySoundStereo(SND_DOOR_CLOSING, SOUND_MIDDLE);
2575 for (x = start; x <= end && !(door_1_done && door_2_done); x += stepsize)
2577 Bitmap *bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2578 GC gc = bitmap->stored_clip_gc;
2580 if (door_state & DOOR_ACTION_1)
2582 int a = MIN(x * door_1.step_offset, end);
2583 int i = (door_state & DOOR_OPEN_1 ? end - a : a);
2587 BlitBitmap(bitmap_db_door, drawto,
2588 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i / 2,
2589 DXSIZE, DYSIZE - i / 2, DX, DY);
2591 ClearRectangle(drawto, DX, DY + DYSIZE - i / 2, DXSIZE, i / 2);
2594 if (door_1.anim_mode == ANIM_HORIZONTAL && x <= DXSIZE)
2596 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
2597 int dst1_x = DX + DXSIZE - i, dst1_y = DY;
2598 int src2_x = DXSIZE - i, src2_y = DOOR_GFX_PAGEY1;
2599 int dst2_x = DX, dst2_y = DY;
2600 int width = i, height = DYSIZE;
2602 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2603 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2606 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2607 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2610 else if (door_1.anim_mode == ANIM_VERTICAL && x <= DYSIZE)
2612 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
2613 int dst1_x = DX, dst1_y = DY + DYSIZE - i;
2614 int src2_x = 0, src2_y = DOOR_GFX_PAGEY1 + DYSIZE - i;
2615 int dst2_x = DX, dst2_y = DY;
2616 int width = DXSIZE, height = i;
2618 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2619 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2622 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2623 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2626 else if (x <= DXSIZE) /* ANIM_DEFAULT */
2628 int j = (door_1.anim_mode == ANIM_DEFAULT ? (DXSIZE - i) / 3 : 0);
2630 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2631 BlitBitmapMasked(bitmap, drawto,
2632 DXSIZE, DOOR_GFX_PAGEY1, i, 77,
2633 DX + DXSIZE - i, DY + j);
2634 BlitBitmapMasked(bitmap, drawto,
2635 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
2636 DX + DXSIZE - i, DY + 140 + j);
2637 SetClipOrigin(bitmap, gc, DX - DXSIZE + i,
2638 DY - (DOOR_GFX_PAGEY1 + j));
2639 BlitBitmapMasked(bitmap, drawto,
2640 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
2642 BlitBitmapMasked(bitmap, drawto,
2643 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
2646 BlitBitmapMasked(bitmap, drawto,
2647 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2649 BlitBitmapMasked(bitmap, drawto,
2650 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2652 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2653 BlitBitmapMasked(bitmap, drawto,
2654 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2655 DX + DXSIZE - i, DY + 77 + j);
2656 BlitBitmapMasked(bitmap, drawto,
2657 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2658 DX + DXSIZE - i, DY + 203 + j);
2661 redraw_mask |= REDRAW_DOOR_1;
2662 door_1_done = (a == end);
2665 if (door_state & DOOR_ACTION_2)
2667 int a = MIN(x * door_2.step_offset, VXSIZE);
2668 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - a : a);
2672 BlitBitmap(bitmap_db_door, drawto,
2673 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i / 2,
2674 VXSIZE, VYSIZE - i / 2, VX, VY);
2676 ClearRectangle(drawto, VX, VY + VYSIZE - i / 2, VXSIZE, i / 2);
2679 if (door_2.anim_mode == ANIM_HORIZONTAL && x <= VXSIZE)
2681 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
2682 int dst1_x = VX + VXSIZE - i, dst1_y = VY;
2683 int src2_x = VXSIZE - i, src2_y = DOOR_GFX_PAGEY2;
2684 int dst2_x = VX, dst2_y = VY;
2685 int width = i, height = VYSIZE;
2687 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2688 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2691 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2692 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2695 else if (door_2.anim_mode == ANIM_VERTICAL && x <= VYSIZE)
2697 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
2698 int dst1_x = VX, dst1_y = VY + VYSIZE - i;
2699 int src2_x = 0, src2_y = DOOR_GFX_PAGEY2 + VYSIZE - i;
2700 int dst2_x = VX, dst2_y = VY;
2701 int width = VXSIZE, height = i;
2703 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2704 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2707 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2708 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2711 else if (x <= VXSIZE) /* ANIM_DEFAULT */
2713 int j = (door_2.anim_mode == ANIM_DEFAULT ? (VXSIZE - i) / 3 : 0);
2715 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2716 BlitBitmapMasked(bitmap, drawto,
2717 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
2718 VX + VXSIZE - i, VY + j);
2719 SetClipOrigin(bitmap, gc,
2720 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2721 BlitBitmapMasked(bitmap, drawto,
2722 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
2725 BlitBitmapMasked(bitmap, drawto,
2726 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2727 i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
2728 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2729 BlitBitmapMasked(bitmap, drawto,
2730 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2732 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2735 redraw_mask |= REDRAW_DOOR_2;
2736 door_2_done = (a == VXSIZE);
2741 if (game_status == GAME_MODE_MAIN)
2744 if (!(door_state & DOOR_NO_DELAY))
2745 WaitUntilDelayReached(&door_delay, door_delay_value);
2750 if (setup.quick_doors)
2752 StopSound(SND_DOOR_OPENING);
2753 StopSound(SND_DOOR_CLOSING);
2757 if (door_state & DOOR_ACTION_1)
2758 door1 = door_state & DOOR_ACTION_1;
2759 if (door_state & DOOR_ACTION_2)
2760 door2 = door_state & DOOR_ACTION_2;
2762 return (door1 | door2);
2765 void DrawSpecialEditorDoor()
2767 /* draw bigger toolbox window */
2768 BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
2769 DOOR_GFX_PAGEX7, 0, EXSIZE + 8, 8,
2771 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2772 EX - 4, VY - 4, EXSIZE + 8, EYSIZE - VYSIZE + 4,
2775 redraw_mask |= REDRAW_ALL;
2778 void UndrawSpecialEditorDoor()
2780 /* draw normal tape recorder window */
2781 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2782 EX - 4, EY - 12, EXSIZE + 8, EYSIZE - VYSIZE + 12,
2785 redraw_mask |= REDRAW_ALL;
2789 /* ---------- new tool button stuff ---------------------------------------- */
2791 /* graphic position values for tool buttons */
2792 #define TOOL_BUTTON_YES_XPOS 2
2793 #define TOOL_BUTTON_YES_YPOS 250
2794 #define TOOL_BUTTON_YES_GFX_YPOS 0
2795 #define TOOL_BUTTON_YES_XSIZE 46
2796 #define TOOL_BUTTON_YES_YSIZE 28
2797 #define TOOL_BUTTON_NO_XPOS 52
2798 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2799 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2800 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2801 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2802 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2803 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2804 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2805 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2806 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2807 #define TOOL_BUTTON_PLAYER_XSIZE 30
2808 #define TOOL_BUTTON_PLAYER_YSIZE 30
2809 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2810 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2811 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2812 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2813 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2814 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2815 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2816 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2817 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2818 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2819 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2820 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2821 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2822 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2823 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2824 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2825 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2826 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2827 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2828 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2837 } toolbutton_info[NUM_TOOL_BUTTONS] =
2840 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2841 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2842 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2847 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2848 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2849 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2854 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2855 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2856 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2857 TOOL_CTRL_ID_CONFIRM,
2861 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2862 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2863 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2864 TOOL_CTRL_ID_PLAYER_1,
2868 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2869 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2870 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2871 TOOL_CTRL_ID_PLAYER_2,
2875 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2876 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2877 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2878 TOOL_CTRL_ID_PLAYER_3,
2882 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2883 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2884 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2885 TOOL_CTRL_ID_PLAYER_4,
2890 void CreateToolButtons()
2894 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2896 Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2897 Bitmap *deco_bitmap = None;
2898 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2899 struct GadgetInfo *gi;
2900 unsigned long event_mask;
2901 int gd_xoffset, gd_yoffset;
2902 int gd_x1, gd_x2, gd_y;
2905 event_mask = GD_EVENT_RELEASED;
2907 gd_xoffset = toolbutton_info[i].xpos;
2908 gd_yoffset = toolbutton_info[i].ypos;
2909 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2910 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2911 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2913 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2915 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
2917 getMiniGraphicSource(PLAYER_NR_GFX(IMG_PLAYER_1, player_nr),
2918 &deco_bitmap, &deco_x, &deco_y);
2919 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2920 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2923 gi = CreateGadget(GDI_CUSTOM_ID, id,
2924 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2925 GDI_X, DX + toolbutton_info[i].x,
2926 GDI_Y, DY + toolbutton_info[i].y,
2927 GDI_WIDTH, toolbutton_info[i].width,
2928 GDI_HEIGHT, toolbutton_info[i].height,
2929 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2930 GDI_STATE, GD_BUTTON_UNPRESSED,
2931 GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
2932 GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
2933 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
2934 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2935 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2936 GDI_DECORATION_SHIFTING, 1, 1,
2937 GDI_EVENT_MASK, event_mask,
2938 GDI_CALLBACK_ACTION, HandleToolButtons,
2942 Error(ERR_EXIT, "cannot create gadget");
2944 tool_gadget[id] = gi;
2948 void FreeToolButtons()
2952 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2953 FreeGadget(tool_gadget[i]);
2956 static void UnmapToolButtons()
2960 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2961 UnmapGadget(tool_gadget[i]);
2964 static void HandleToolButtons(struct GadgetInfo *gi)
2966 request_gadget_id = gi->custom_id;
2974 boolean is_rnd_to_em_mapping; /* unique mapping EM <-> RND */
2975 boolean is_backside; /* backside of moving element */
2981 mapping_EM_to_RND_list[] =
2984 Xblank, TRUE, FALSE,
2988 Yacid_splash_eB, FALSE, TRUE,
2989 EL_ACID_SPLASH_RIGHT, -1, -1
2992 Yacid_splash_wB, FALSE, TRUE,
2993 EL_ACID_SPLASH_LEFT, -1, -1
2996 #ifdef EM_ENGINE_BAD_ROLL
2998 Xstone_force_e, FALSE, FALSE,
2999 EL_ROCK, -1, MV_BIT_RIGHT
3002 Xstone_force_w, FALSE, FALSE,
3003 EL_ROCK, -1, MV_BIT_LEFT
3006 Xnut_force_e, FALSE, FALSE,
3007 EL_NUT, -1, MV_BIT_RIGHT
3010 Xnut_force_w, FALSE, FALSE,
3011 EL_NUT, -1, MV_BIT_LEFT
3014 Xspring_force_e, FALSE, FALSE,
3015 EL_SPRING, -1, MV_BIT_RIGHT
3018 Xspring_force_w, FALSE, FALSE,
3019 EL_SPRING, -1, MV_BIT_LEFT
3022 Xemerald_force_e, FALSE, FALSE,
3023 EL_EMERALD, -1, MV_BIT_RIGHT
3026 Xemerald_force_w, FALSE, FALSE,
3027 EL_EMERALD, -1, MV_BIT_LEFT
3030 Xdiamond_force_e, FALSE, FALSE,
3031 EL_DIAMOND, -1, MV_BIT_RIGHT
3034 Xdiamond_force_w, FALSE, FALSE,
3035 EL_DIAMOND, -1, MV_BIT_LEFT
3038 Xbomb_force_e, FALSE, FALSE,
3039 EL_BOMB, -1, MV_BIT_RIGHT
3042 Xbomb_force_w, FALSE, FALSE,
3043 EL_BOMB, -1, MV_BIT_LEFT
3045 #endif /* EM_ENGINE_BAD_ROLL */
3048 Xstone, TRUE, FALSE,
3052 Xstone_pause, FALSE, FALSE,
3056 Xstone_fall, FALSE, FALSE,
3060 Ystone_s, FALSE, FALSE,
3061 EL_ROCK, ACTION_FALLING, -1
3064 Ystone_sB, FALSE, TRUE,
3065 EL_ROCK, ACTION_FALLING, -1
3068 Ystone_e, FALSE, FALSE,
3069 EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT
3072 Ystone_eB, FALSE, TRUE,
3073 EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT
3076 Ystone_w, FALSE, FALSE,
3077 EL_ROCK, ACTION_MOVING, MV_BIT_LEFT
3080 Ystone_wB, FALSE, TRUE,
3081 EL_ROCK, ACTION_MOVING, MV_BIT_LEFT
3088 Xnut_pause, FALSE, FALSE,
3092 Xnut_fall, FALSE, FALSE,
3096 Ynut_s, FALSE, FALSE,
3097 EL_NUT, ACTION_FALLING, -1
3100 Ynut_sB, FALSE, TRUE,
3101 EL_NUT, ACTION_FALLING, -1
3104 Ynut_e, FALSE, FALSE,
3105 EL_NUT, ACTION_MOVING, MV_BIT_RIGHT
3108 Ynut_eB, FALSE, TRUE,
3109 EL_NUT, ACTION_MOVING, MV_BIT_RIGHT
3112 Ynut_w, FALSE, FALSE,
3113 EL_NUT, ACTION_MOVING, MV_BIT_LEFT
3116 Ynut_wB, FALSE, TRUE,
3117 EL_NUT, ACTION_MOVING, MV_BIT_LEFT
3120 Xbug_n, TRUE, FALSE,
3124 Xbug_e, TRUE, FALSE,
3125 EL_BUG_RIGHT, -1, -1
3128 Xbug_s, TRUE, FALSE,
3132 Xbug_w, TRUE, FALSE,
3136 Xbug_gon, FALSE, FALSE,
3140 Xbug_goe, FALSE, FALSE,
3141 EL_BUG_RIGHT, -1, -1
3144 Xbug_gos, FALSE, FALSE,
3148 Xbug_gow, FALSE, FALSE,
3152 Ybug_n, FALSE, FALSE,
3153 EL_BUG, ACTION_MOVING, MV_BIT_UP
3156 Ybug_nB, FALSE, TRUE,
3157 EL_BUG, ACTION_MOVING, MV_BIT_UP
3160 Ybug_e, FALSE, FALSE,
3161 EL_BUG, ACTION_MOVING, MV_BIT_RIGHT
3164 Ybug_eB, FALSE, TRUE,
3165 EL_BUG, ACTION_MOVING, MV_BIT_RIGHT
3168 Ybug_s, FALSE, FALSE,
3169 EL_BUG, ACTION_MOVING, MV_BIT_DOWN
3172 Ybug_sB, FALSE, TRUE,
3173 EL_BUG, ACTION_MOVING, MV_BIT_DOWN
3176 Ybug_w, FALSE, FALSE,
3177 EL_BUG, ACTION_MOVING, MV_BIT_LEFT
3180 Ybug_wB, FALSE, TRUE,
3181 EL_BUG, ACTION_MOVING, MV_BIT_LEFT
3184 Ybug_w_n, FALSE, FALSE,
3185 EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_UP
3188 Ybug_n_e, FALSE, FALSE,
3189 EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3192 Ybug_e_s, FALSE, FALSE,
3193 EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
3196 Ybug_s_w, FALSE, FALSE,
3197 EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3200 Ybug_e_n, FALSE, FALSE,
3201 EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
3204 Ybug_s_e, FALSE, FALSE,
3205 EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3208 Ybug_w_s, FALSE, FALSE,
3209 EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
3212 Ybug_n_w, FALSE, FALSE,
3213 EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3216 Ybug_stone, FALSE, FALSE,
3217 EL_BUG, ACTION_SMASHED_BY_ROCK, -1
3220 Ybug_spring, FALSE, FALSE,
3221 EL_BUG, ACTION_SMASHED_BY_SPRING, -1
3224 Xtank_n, TRUE, FALSE,
3225 EL_SPACESHIP_UP, -1, -1
3228 Xtank_e, TRUE, FALSE,
3229 EL_SPACESHIP_RIGHT, -1, -1
3232 Xtank_s, TRUE, FALSE,
3233 EL_SPACESHIP_DOWN, -1, -1
3236 Xtank_w, TRUE, FALSE,
3237 EL_SPACESHIP_LEFT, -1, -1
3240 Xtank_gon, FALSE, FALSE,
3241 EL_SPACESHIP_UP, -1, -1
3244 Xtank_goe, FALSE, FALSE,
3245 EL_SPACESHIP_RIGHT, -1, -1
3248 Xtank_gos, FALSE, FALSE,
3249 EL_SPACESHIP_DOWN, -1, -1
3252 Xtank_gow, FALSE, FALSE,
3253 EL_SPACESHIP_LEFT, -1, -1
3256 Ytank_n, FALSE, FALSE,
3257 EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP
3260 Ytank_nB, FALSE, TRUE,
3261 EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP
3264 Ytank_e, FALSE, FALSE,
3265 EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT
3268 Ytank_eB, FALSE, TRUE,
3269 EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT
3272 Ytank_s, FALSE, FALSE,
3273 EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN
3276 Ytank_sB, FALSE, TRUE,
3277 EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN
3280 Ytank_w, FALSE, FALSE,
3281 EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT
3284 Ytank_wB, FALSE, TRUE,
3285 EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT
3288 Ytank_w_n, FALSE, FALSE,
3289 EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_UP
3292 Ytank_n_e, FALSE, FALSE,
3293 EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3296 Ytank_e_s, FALSE, FALSE,
3297 EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
3300 Ytank_s_w, FALSE, FALSE,
3301 EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3304 Ytank_e_n, FALSE, FALSE,
3305 EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
3308 Ytank_s_e, FALSE, FALSE,
3309 EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3312 Ytank_w_s, FALSE, FALSE,
3313 EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
3316 Ytank_n_w, FALSE, FALSE,
3317 EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3320 Ytank_stone, FALSE, FALSE,
3321 EL_SPACESHIP, ACTION_SMASHED_BY_ROCK, -1
3324 Ytank_spring, FALSE, FALSE,
3325 EL_SPACESHIP, ACTION_SMASHED_BY_SPRING, -1
3328 Xandroid, TRUE, FALSE,
3329 EL_EMC_ANDROID, ACTION_ACTIVE, -1
3332 Xandroid_1_n, FALSE, FALSE,
3333 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_UP
3336 Xandroid_2_n, FALSE, FALSE,
3337 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_UP
3340 Xandroid_1_e, FALSE, FALSE,
3341 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_RIGHT
3344 Xandroid_2_e, FALSE, FALSE,
3345 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_RIGHT
3348 Xandroid_1_w, FALSE, FALSE,
3349 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_LEFT
3352 Xandroid_2_w, FALSE, FALSE,
3353 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_LEFT
3356 Xandroid_1_s, FALSE, FALSE,
3357 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_DOWN
3360 Xandroid_2_s, FALSE, FALSE,
3361 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_DOWN
3364 Yandroid_n, FALSE, FALSE,
3365 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_UP
3368 Yandroid_nB, FALSE, TRUE,
3369 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_UP
3372 Yandroid_ne, FALSE, FALSE,
3373 EL_EMC_ANDROID, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3376 Yandroid_neB, FALSE, TRUE,
3377 EL_EMC_ANDROID, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3380 Yandroid_e, FALSE, FALSE,
3381 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_RIGHT
3384 Yandroid_eB, FALSE, TRUE,
3385 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_RIGHT
3388 Yandroid_se, FALSE, FALSE,
3389 EL_EMC_ANDROID, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3392 Yandroid_seB, FALSE, TRUE,
3393 EL_EMC_ANDROID, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3396 Yandroid_s, FALSE, FALSE,
3397 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_DOWN
3400 Yandroid_sB, FALSE, TRUE,
3401 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_DOWN
3404 Yandroid_sw, FALSE, FALSE,
3405 EL_EMC_ANDROID, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3408 Yandroid_swB, FALSE, TRUE,
3409 EL_EMC_ANDROID, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3412 Yandroid_w, FALSE, FALSE,
3413 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_LEFT
3416 Yandroid_wB, FALSE, TRUE,
3417 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_LEFT
3420 Yandroid_nw, FALSE, FALSE,
3421 EL_EMC_ANDROID, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3424 Yandroid_nwB, FALSE, TRUE,
3425 EL_EMC_ANDROID, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3428 Xspring, TRUE, FALSE,
3432 Xspring_pause, FALSE, FALSE,
3436 Xspring_e, FALSE, FALSE,
3440 Xspring_w, FALSE, FALSE,
3444 Xspring_fall, FALSE, FALSE,
3448 Yspring_s, FALSE, FALSE,
3449 EL_SPRING, ACTION_FALLING, -1
3452 Yspring_sB, FALSE, TRUE,
3453 EL_SPRING, ACTION_FALLING, -1
3456 Yspring_e, FALSE, FALSE,
3457 EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT
3460 Yspring_eB, FALSE, TRUE,
3461 EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT
3464 Yspring_w, FALSE, FALSE,
3465 EL_SPRING, ACTION_MOVING, MV_BIT_LEFT
3468 Yspring_wB, FALSE, TRUE,
3469 EL_SPRING, ACTION_MOVING, MV_BIT_LEFT
3472 Yspring_kill_e, FALSE, FALSE,
3473 EL_ROBOT, ACTION_SLURPED_BY_SPRING, MV_BIT_RIGHT
3476 Yspring_kill_eB, FALSE, TRUE,
3477 EL_ROBOT, ACTION_SLURPED_BY_SPRING, MV_BIT_RIGHT
3480 Yspring_kill_w, FALSE, FALSE,
3481 EL_ROBOT, ACTION_SLURPED_BY_SPRING, MV_BIT_LEFT
3484 Yspring_kill_wB, FALSE, TRUE,
3485 EL_ROBOT, ACTION_SLURPED_BY_SPRING, MV_BIT_LEFT
3488 Xeater_n, TRUE, FALSE,
3492 Xeater_e, FALSE, FALSE,
3496 Xeater_w, FALSE, FALSE,
3500 Xeater_s, FALSE, FALSE,
3504 Yeater_n, FALSE, FALSE,
3505 EL_YAMYAM, ACTION_MOVING, MV_BIT_UP
3508 Yeater_nB, FALSE, TRUE,
3509 EL_YAMYAM, ACTION_MOVING, MV_BIT_UP
3512 Yeater_e, FALSE, FALSE,
3513 EL_YAMYAM, ACTION_MOVING, MV_BIT_RIGHT
3516 Yeater_eB, FALSE, TRUE,
3517 EL_YAMYAM, ACTION_MOVING, MV_BIT_RIGHT
3520 Yeater_s, FALSE, FALSE,
3521 EL_YAMYAM, ACTION_MOVING, MV_BIT_DOWN
3524 Yeater_sB, FALSE, TRUE,
3525 EL_YAMYAM, ACTION_MOVING, MV_BIT_DOWN
3528 Yeater_w, FALSE, FALSE,
3529 EL_YAMYAM, ACTION_MOVING, MV_BIT_LEFT
3532 Yeater_wB, FALSE, TRUE,
3533 EL_YAMYAM, ACTION_MOVING, MV_BIT_LEFT
3536 Yeater_stone, FALSE, FALSE,
3537 EL_YAMYAM, ACTION_SMASHED_BY_ROCK, -1
3540 Yeater_spring, FALSE, FALSE,
3541 EL_YAMYAM, ACTION_SMASHED_BY_SPRING, -1
3544 Xalien, TRUE, FALSE,
3548 Xalien_pause, FALSE, FALSE,
3552 Yalien_n, FALSE, FALSE,
3553 EL_ROBOT, ACTION_MOVING, MV_BIT_UP
3556 Yalien_nB, FALSE, TRUE,
3557 EL_ROBOT, ACTION_MOVING, MV_BIT_UP
3560 Yalien_e, FALSE, FALSE,
3561 EL_ROBOT, ACTION_MOVING, MV_BIT_RIGHT
3564 Yalien_eB, FALSE, TRUE,
3565 EL_ROBOT, ACTION_MOVING, MV_BIT_RIGHT
3568 Yalien_s, FALSE, FALSE,
3569 EL_ROBOT, ACTION_MOVING, MV_BIT_DOWN
3572 Yalien_sB, FALSE, TRUE,
3573 EL_ROBOT, ACTION_MOVING, MV_BIT_DOWN
3576 Yalien_w, FALSE, FALSE,
3577 EL_ROBOT, ACTION_MOVING, MV_BIT_LEFT
3580 Yalien_wB, FALSE, TRUE,
3581 EL_ROBOT, ACTION_MOVING, MV_BIT_LEFT
3584 Yalien_stone, FALSE, FALSE,
3585 EL_ROBOT, ACTION_SMASHED_BY_ROCK, -1
3588 Yalien_spring, FALSE, FALSE,
3589 EL_ROBOT, ACTION_SMASHED_BY_SPRING, -1
3592 Xemerald, TRUE, FALSE,
3596 Xemerald_pause, FALSE, FALSE,
3600 Xemerald_fall, FALSE, FALSE,
3604 Xemerald_shine, FALSE, FALSE,
3605 EL_EMERALD, ACTION_TWINKLING, -1
3608 Yemerald_s, FALSE, FALSE,
3609 EL_EMERALD, ACTION_FALLING, -1
3612 Yemerald_sB, FALSE, TRUE,
3613 EL_EMERALD, ACTION_FALLING, -1
3616 Yemerald_e, FALSE, FALSE,
3617 EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT
3620 Yemerald_eB, FALSE, TRUE,
3621 EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT
3624 Yemerald_w, FALSE, FALSE,
3625 EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT
3628 Yemerald_wB, FALSE, TRUE,
3629 EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT
3632 Yemerald_eat, FALSE, FALSE,
3633 EL_EMERALD, ACTION_COLLECTING, -1
3636 Yemerald_stone, FALSE, FALSE,
3637 EL_NUT, ACTION_BREAKING, -1
3640 Xdiamond, TRUE, FALSE,
3644 Xdiamond_pause, FALSE, FALSE,
3648 Xdiamond_fall, FALSE, FALSE,
3652 Xdiamond_shine, FALSE, FALSE,
3653 EL_DIAMOND, ACTION_TWINKLING, -1
3656 Ydiamond_s, FALSE, FALSE,
3657 EL_DIAMOND, ACTION_FALLING, -1
3660 Ydiamond_sB, FALSE, TRUE,
3661 EL_DIAMOND, ACTION_FALLING, -1
3664 Ydiamond_e, FALSE, FALSE,
3665 EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT
3668 Ydiamond_eB, FALSE, TRUE,
3669 EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT
3672 Ydiamond_w, FALSE, FALSE,
3673 EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT
3676 Ydiamond_wB, FALSE, TRUE,
3677 EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT
3680 Ydiamond_eat, FALSE, FALSE,
3681 EL_DIAMOND, ACTION_COLLECTING, -1
3684 Ydiamond_stone, FALSE, FALSE,
3685 EL_DIAMOND, ACTION_SMASHED_BY_ROCK, -1
3688 Xdrip_fall, TRUE, FALSE,
3689 EL_AMOEBA_DROP, -1, -1
3692 Xdrip_stretch, FALSE, FALSE,
3693 EL_AMOEBA_DROP, ACTION_FALLING, -1
3696 Xdrip_stretchB, FALSE, TRUE,
3697 EL_AMOEBA_DROP, ACTION_FALLING, -1
3700 Xdrip_eat, FALSE, FALSE,
3701 EL_AMOEBA_DROP, ACTION_GROWING, -1
3704 Ydrip_s1, FALSE, FALSE,
3705 EL_AMOEBA_DROP, ACTION_FALLING, -1
3708 Ydrip_s1B, FALSE, TRUE,
3709 EL_AMOEBA_DROP, ACTION_FALLING, -1
3712 Ydrip_s2, FALSE, FALSE,
3713 EL_AMOEBA_DROP, ACTION_FALLING, -1
3716 Ydrip_s2B, FALSE, TRUE,
3717 EL_AMOEBA_DROP, ACTION_FALLING, -1
3724 Xbomb_pause, FALSE, FALSE,
3728 Xbomb_fall, FALSE, FALSE,
3732 Ybomb_s, FALSE, FALSE,
3733 EL_BOMB, ACTION_FALLING, -1
3736 Ybomb_sB, FALSE, TRUE,
3737 EL_BOMB, ACTION_FALLING, -1
3740 Ybomb_e, FALSE, FALSE,
3741 EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT
3744 Ybomb_eB, FALSE, TRUE,
3745 EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT
3748 Ybomb_w, FALSE, FALSE,
3749 EL_BOMB, ACTION_MOVING, MV_BIT_LEFT
3752 Ybomb_wB, FALSE, TRUE,
3753 EL_BOMB, ACTION_MOVING, MV_BIT_LEFT
3756 Ybomb_eat, FALSE, FALSE,
3757 EL_BOMB, ACTION_SMASHED_BY_ROCK, -1
3760 Xballoon, TRUE, FALSE,
3764 Yballoon_n, FALSE, FALSE,
3765 EL_BALLOON, ACTION_MOVING, MV_BIT_UP
3768 Yballoon_nB, FALSE, TRUE,
3769 EL_BALLOON, ACTION_MOVING, MV_BIT_UP
3772 Yballoon_e, FALSE, FALSE,
3773 EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT
3776 Yballoon_eB, FALSE, TRUE,
3777 EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT
3780 Yballoon_s, FALSE, FALSE,
3781 EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN
3784 Yballoon_sB, FALSE, TRUE,
3785 EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN
3788 Yballoon_w, FALSE, FALSE,
3789 EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT
3792 Yballoon_wB, FALSE, TRUE,
3793 EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT
3796 Xgrass, TRUE, FALSE,
3797 EL_EMC_GRASS, -1, -1
3800 Ygrass_nB, FALSE, TRUE,
3801 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_UP
3804 Ygrass_eB, FALSE, TRUE,
3805 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_RIGHT
3808 Ygrass_sB, FALSE, TRUE,
3809 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_DOWN
3812 Ygrass_wB, FALSE, TRUE,
3813 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_LEFT
3820 Ydirt_nB, FALSE, TRUE,
3821 EL_SAND, ACTION_DIGGING, MV_BIT_UP
3824 Ydirt_eB, FALSE, TRUE,
3825 EL_SAND, ACTION_DIGGING, MV_BIT_RIGHT
3828 Ydirt_sB, FALSE, TRUE,
3829 EL_SAND, ACTION_DIGGING, MV_BIT_DOWN
3832 Ydirt_wB, FALSE, TRUE,
3833 EL_SAND, ACTION_DIGGING, MV_BIT_LEFT
3836 Xacid_ne, TRUE, FALSE,
3837 EL_ACID_POOL_TOPRIGHT, -1, -1
3840 Xacid_se, TRUE, FALSE,
3841 EL_ACID_POOL_BOTTOMRIGHT, -1, -1
3844 Xacid_s, TRUE, FALSE,
3845 EL_ACID_POOL_BOTTOM, -1, -1
3848 Xacid_sw, TRUE, FALSE,
3849 EL_ACID_POOL_BOTTOMLEFT, -1, -1
3852 Xacid_nw, TRUE, FALSE,
3853 EL_ACID_POOL_TOPLEFT, -1, -1
3856 Xacid_1, TRUE, FALSE,
3860 Xacid_2, FALSE, FALSE,
3864 Xacid_3, FALSE, FALSE,
3868 Xacid_4, FALSE, FALSE,
3872 Xacid_5, FALSE, FALSE,
3876 Xacid_6, FALSE, FALSE,
3880 Xacid_7, FALSE, FALSE,
3884 Xacid_8, FALSE, FALSE,
3888 Xball_1, TRUE, FALSE,
3889 EL_EMC_MAGIC_BALL, -1, -1
3892 Xball_1B, FALSE, TRUE,
3893 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
3896 Xball_2, FALSE, FALSE,
3897 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
3900 Xball_2B, FALSE, TRUE,
3901 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
3904 Yball_eat, FALSE, FALSE,
3905 EL_EMC_MAGIC_BALL, ACTION_DROPPING, -1
3908 Xgrow_ns, TRUE, FALSE,
3909 EL_EXPANDABLE_WALL_VERTICAL, -1, -1
3912 Ygrow_ns_eat, FALSE, FALSE,
3913 EL_EXPANDABLE_WALL_VERTICAL, ACTION_GROWING, -1
3916 Xgrow_ew, TRUE, FALSE,
3917 EL_EXPANDABLE_WALL_HORIZONTAL, -1, -1
3920 Ygrow_ew_eat, FALSE, FALSE,
3921 EL_EXPANDABLE_WALL_HORIZONTAL, ACTION_GROWING, -1
3924 Xwonderwall, TRUE, FALSE,
3925 EL_MAGIC_WALL, -1, -1
3928 XwonderwallB, FALSE, FALSE,
3929 EL_MAGIC_WALL, ACTION_ACTIVE, -1
3932 Xamoeba_1, TRUE, FALSE,
3933 EL_AMOEBA_DRY, ACTION_OTHER, -1
3936 Xamoeba_2, FALSE, FALSE,
3937 EL_AMOEBA_DRY, ACTION_OTHER, -1
3940 Xamoeba_3, FALSE, FALSE,
3941 EL_AMOEBA_DRY, ACTION_OTHER, -1
3944 Xamoeba_4, FALSE, FALSE,
3945 EL_AMOEBA_DRY, ACTION_OTHER, -1
3948 Xamoeba_5, FALSE, FALSE,
3949 EL_AMOEBA_WET, ACTION_OTHER, -1
3952 Xamoeba_6, FALSE, FALSE,
3953 EL_AMOEBA_WET, ACTION_OTHER, -1
3956 Xamoeba_7, FALSE, FALSE,
3957 EL_AMOEBA_WET, ACTION_OTHER, -1
3960 Xamoeba_8, FALSE, FALSE,
3961 EL_AMOEBA_WET, ACTION_OTHER, -1
3964 Xdoor_1, TRUE, FALSE,
3965 EL_EM_GATE_1, -1, -1
3968 Xdoor_2, TRUE, FALSE,
3969 EL_EM_GATE_2, -1, -1
3972 Xdoor_3, TRUE, FALSE,
3973 EL_EM_GATE_3, -1, -1
3976 Xdoor_4, TRUE, FALSE,
3977 EL_EM_GATE_4, -1, -1
3980 Xdoor_5, TRUE, FALSE,
3981 EL_EM_GATE_5, -1, -1
3984 Xdoor_6, TRUE, FALSE,
3985 EL_EM_GATE_6, -1, -1
3988 Xdoor_7, TRUE, FALSE,
3989 EL_EM_GATE_7, -1, -1
3992 Xdoor_8, TRUE, FALSE,
3993 EL_EM_GATE_8, -1, -1
3996 Xkey_1, TRUE, FALSE,
4000 Xkey_2, TRUE, FALSE,
4004 Xkey_3, TRUE, FALSE,
4008 Xkey_4, TRUE, FALSE,
4012 Xkey_5, TRUE, FALSE,
4016 Xkey_6, TRUE, FALSE,
4020 Xkey_7, TRUE, FALSE,
4024 Xkey_8, TRUE, FALSE,
4028 Xwind_n, TRUE, FALSE,
4029 EL_BALLOON_SWITCH_UP, -1, -1
4032 Xwind_e, TRUE, FALSE,
4033 EL_BALLOON_SWITCH_RIGHT, -1, -1
4036 Xwind_s, TRUE, FALSE,
4037 EL_BALLOON_SWITCH_DOWN, -1, -1
4040 Xwind_w, TRUE, FALSE,
4041 EL_BALLOON_SWITCH_LEFT, -1, -1
4044 Xwind_nesw, TRUE, FALSE,
4045 EL_BALLOON_SWITCH_ANY, -1, -1
4048 Xwind_stop, TRUE, FALSE,
4049 EL_BALLOON_SWITCH_NONE, -1, -1
4053 EL_EXIT_CLOSED, -1, -1
4056 Xexit_1, TRUE, FALSE,
4057 EL_EXIT_OPEN, -1, -1
4060 Xexit_2, FALSE, FALSE,
4061 EL_EXIT_OPEN, -1, -1
4064 Xexit_3, FALSE, FALSE,
4065 EL_EXIT_OPEN, -1, -1
4068 Xdynamite, TRUE, FALSE,
4072 Ydynamite_eat, FALSE, FALSE,
4073 EL_DYNAMITE, ACTION_COLLECTING, -1
4076 Xdynamite_1, TRUE, FALSE,
4077 EL_DYNAMITE_ACTIVE, -1, -1
4080 Xdynamite_2, FALSE, FALSE,
4081 EL_DYNAMITE_ACTIVE, -1, -1
4084 Xdynamite_3, FALSE, FALSE,
4085 EL_DYNAMITE_ACTIVE, -1, -1
4088 Xdynamite_4, FALSE, FALSE,
4089 EL_DYNAMITE_ACTIVE, -1, -1
4092 Xbumper, TRUE, FALSE,
4093 EL_EMC_SPRING_BUMPER, -1, -1
4096 XbumperB, FALSE, FALSE,
4097 EL_EMC_SPRING_BUMPER, ACTION_ACTIVE, -1
4100 Xwheel, TRUE, FALSE,
4101 EL_ROBOT_WHEEL, -1, -1
4104 XwheelB, FALSE, FALSE,
4105 EL_ROBOT_WHEEL, ACTION_ACTIVE, -1
4108 Xswitch, TRUE, FALSE,
4109 EL_EMC_MAGIC_BALL_SWITCH, -1, -1
4112 XswitchB, FALSE, FALSE,
4113 EL_EMC_MAGIC_BALL_SWITCH, ACTION_ACTIVE, -1
4117 EL_QUICKSAND_EMPTY, -1, -1
4120 Xsand_stone, TRUE, FALSE,
4121 EL_QUICKSAND_FULL, -1, -1
4124 Xsand_stonein_1, FALSE, FALSE,
4125 EL_ROCK, ACTION_FILLING, -1
4128 Xsand_stonein_2, FALSE, FALSE,
4129 EL_ROCK, ACTION_FILLING, -1
4132 Xsand_stonein_3, FALSE, FALSE,
4133 EL_ROCK, ACTION_FILLING, -1
4136 Xsand_stonein_4, FALSE, FALSE,
4137 EL_ROCK, ACTION_FILLING, -1
4140 Xsand_stonesand_1, FALSE, FALSE,
4141 EL_QUICKSAND_FULL, -1, -1
4144 Xsand_stonesand_2, FALSE, FALSE,
4145 EL_QUICKSAND_FULL, -1, -1
4148 Xsand_stonesand_3, FALSE, FALSE,
4149 EL_QUICKSAND_FULL, -1, -1
4152 Xsand_stonesand_4, FALSE, FALSE,
4153 EL_QUICKSAND_FULL, -1, -1
4156 Xsand_stoneout_1, FALSE, FALSE,
4157 EL_ROCK, ACTION_EMPTYING, -1
4160 Xsand_stoneout_2, FALSE, FALSE,
4161 EL_ROCK, ACTION_EMPTYING, -1
4164 Xsand_sandstone_1, FALSE, FALSE,
4165 EL_QUICKSAND_FULL, -1, -1
4168 Xsand_sandstone_2, FALSE, FALSE,
4169 EL_QUICKSAND_FULL, -1, -1
4172 Xsand_sandstone_3, FALSE, FALSE,
4173 EL_QUICKSAND_FULL, -1, -1
4176 Xsand_sandstone_4, FALSE, FALSE,
4177 EL_QUICKSAND_FULL, -1, -1
4180 Xplant, TRUE, FALSE,
4181 EL_EMC_PLANT, -1, -1
4184 Yplant, FALSE, FALSE,
4185 EL_EMC_PLANT, -1, -1
4188 Xlenses, TRUE, FALSE,
4189 EL_EMC_LENSES, -1, -1
4192 Xmagnify, TRUE, FALSE,
4193 EL_EMC_MAGNIFIER, -1, -1
4196 Xdripper, TRUE, FALSE,
4197 EL_EMC_DRIPPER, -1, -1
4200 XdripperB, FALSE, FALSE,
4201 EL_EMC_DRIPPER, ACTION_ACTIVE, -1
4204 Xfake_blank, TRUE, FALSE,
4205 EL_INVISIBLE_WALL, -1, -1
4208 Xfake_blankB, FALSE, FALSE,
4209 EL_INVISIBLE_WALL, ACTION_ACTIVE, -1
4212 Xfake_grass, TRUE, FALSE,
4213 EL_EMC_FAKE_GRASS, -1, -1
4216 Xfake_grassB, FALSE, FALSE,
4217 EL_EMC_FAKE_GRASS, ACTION_ACTIVE, -1
4220 Xfake_door_1, TRUE, FALSE,
4221 EL_EM_GATE_1_GRAY, -1, -1
4224 Xfake_door_2, TRUE, FALSE,
4225 EL_EM_GATE_2_GRAY, -1, -1
4228 Xfake_door_3, TRUE, FALSE,
4229 EL_EM_GATE_3_GRAY, -1, -1
4232 Xfake_door_4, TRUE, FALSE,
4233 EL_EM_GATE_4_GRAY, -1, -1
4236 Xfake_door_5, TRUE, FALSE,
4237 EL_EM_GATE_5_GRAY, -1, -1
4240 Xfake_door_6, TRUE, FALSE,
4241 EL_EM_GATE_6_GRAY, -1, -1
4244 Xfake_door_7, TRUE, FALSE,
4245 EL_EM_GATE_7_GRAY, -1, -1
4248 Xfake_door_8, TRUE, FALSE,
4249 EL_EM_GATE_8_GRAY, -1, -1
4252 Xsteel_1, TRUE, FALSE,
4253 EL_STEELWALL, -1, -1
4256 Xsteel_2, TRUE, FALSE,
4257 EL_EMC_STEELWALL_2, -1, -1
4260 Xsteel_3, TRUE, FALSE,
4261 EL_EMC_STEELWALL_3, -1, -1
4264 Xsteel_4, TRUE, FALSE,
4265 EL_EMC_STEELWALL_4, -1, -1
4268 Xwall_1, TRUE, FALSE,
4272 Xwall_2, TRUE, FALSE,
4273 EL_EMC_WALL_14, -1, -1
4276 Xwall_3, TRUE, FALSE,
4277 EL_EMC_WALL_15, -1, -1
4280 Xwall_4, TRUE, FALSE,
4281 EL_EMC_WALL_16, -1, -1
4284 Xround_wall_1, TRUE, FALSE,
4285 EL_WALL_SLIPPERY, -1, -1
4288 Xround_wall_2, TRUE, FALSE,
4289 EL_EMC_WALL_SLIPPERY_2, -1, -1
4292 Xround_wall_3, TRUE, FALSE,
4293 EL_EMC_WALL_SLIPPERY_3, -1, -1
4296 Xround_wall_4, TRUE, FALSE,
4297 EL_EMC_WALL_SLIPPERY_4, -1, -1
4300 Xdecor_1, TRUE, FALSE,
4301 EL_EMC_WALL_8, -1, -1
4304 Xdecor_2, TRUE, FALSE,
4305 EL_EMC_WALL_6, -1, -1
4308 Xdecor_3, TRUE, FALSE,
4309 EL_EMC_WALL_4, -1, -1
4312 Xdecor_4, TRUE, FALSE,
4313 EL_EMC_WALL_7, -1, -1
4316 Xdecor_5, TRUE, FALSE,
4317 EL_EMC_WALL_5, -1, -1
4320 Xdecor_6, TRUE, FALSE,
4321 EL_EMC_WALL_9, -1, -1
4324 Xdecor_7, TRUE, FALSE,
4325 EL_EMC_WALL_10, -1, -1
4328 Xdecor_8, TRUE, FALSE,
4329 EL_EMC_WALL_1, -1, -1
4332 Xdecor_9, TRUE, FALSE,
4333 EL_EMC_WALL_2, -1, -1
4336 Xdecor_10, TRUE, FALSE,
4337 EL_EMC_WALL_3, -1, -1
4340 Xdecor_11, TRUE, FALSE,
4341 EL_EMC_WALL_11, -1, -1
4344 Xdecor_12, TRUE, FALSE,
4345 EL_EMC_WALL_12, -1, -1
4348 Xalpha_0, TRUE, FALSE,
4349 EL_CHAR('0'), -1, -1
4352 Xalpha_1, TRUE, FALSE,
4353 EL_CHAR('1'), -1, -1
4356 Xalpha_2, TRUE, FALSE,
4357 EL_CHAR('2'), -1, -1
4360 Xalpha_3, TRUE, FALSE,
4361 EL_CHAR('3'), -1, -1
4364 Xalpha_4, TRUE, FALSE,
4365 EL_CHAR('4'), -1, -1
4368 Xalpha_5, TRUE, FALSE,
4369 EL_CHAR('5'), -1, -1
4372 Xalpha_6, TRUE, FALSE,
4373 EL_CHAR('6'), -1, -1
4376 Xalpha_7, TRUE, FALSE,
4377 EL_CHAR('7'), -1, -1
4380 Xalpha_8, TRUE, FALSE,
4381 EL_CHAR('8'), -1, -1
4384 Xalpha_9, TRUE, FALSE,
4385 EL_CHAR('9'), -1, -1
4388 Xalpha_excla, TRUE, FALSE,
4389 EL_CHAR('!'), -1, -1
4392 Xalpha_quote, TRUE, FALSE,
4393 EL_CHAR('"'), -1, -1
4396 Xalpha_comma, TRUE, FALSE,
4397 EL_CHAR(','), -1, -1
4400 Xalpha_minus, TRUE, FALSE,
4401 EL_CHAR('-'), -1, -1
4404 Xalpha_perio, TRUE, FALSE,
4405 EL_CHAR('.'), -1, -1
4408 Xalpha_colon, TRUE, FALSE,
4409 EL_CHAR(':'), -1, -1
4412 Xalpha_quest, TRUE, FALSE,
4413 EL_CHAR('?'), -1, -1
4416 Xalpha_a, TRUE, FALSE,
4417 EL_CHAR('A'), -1, -1
4420 Xalpha_b, TRUE, FALSE,
4421 EL_CHAR('B'), -1, -1
4424 Xalpha_c, TRUE, FALSE,
4425 EL_CHAR('C'), -1, -1
4428 Xalpha_d, TRUE, FALSE,
4429 EL_CHAR('D'), -1, -1
4432 Xalpha_e, TRUE, FALSE,
4433 EL_CHAR('E'), -1, -1
4436 Xalpha_f, TRUE, FALSE,
4437 EL_CHAR('F'), -1, -1
4440 Xalpha_g, TRUE, FALSE,
4441 EL_CHAR('G'), -1, -1
4444 Xalpha_h, TRUE, FALSE,
4445 EL_CHAR('H'), -1, -1
4448 Xalpha_i, TRUE, FALSE,
4449 EL_CHAR('I'), -1, -1
4452 Xalpha_j, TRUE, FALSE,
4453 EL_CHAR('J'), -1, -1
4456 Xalpha_k, TRUE, FALSE,
4457 EL_CHAR('K'), -1, -1
4460 Xalpha_l, TRUE, FALSE,
4461 EL_CHAR('L'), -1, -1
4464 Xalpha_m, TRUE, FALSE,
4465 EL_CHAR('M'), -1, -1
4468 Xalpha_n, TRUE, FALSE,
4469 EL_CHAR('N'), -1, -1
4472 Xalpha_o, TRUE, FALSE,
4473 EL_CHAR('O'), -1, -1
4476 Xalpha_p, TRUE, FALSE,
4477 EL_CHAR('P'), -1, -1
4480 Xalpha_q, TRUE, FALSE,
4481 EL_CHAR('Q'), -1, -1
4484 Xalpha_r, TRUE, FALSE,
4485 EL_CHAR('R'), -1, -1
4488 Xalpha_s, TRUE, FALSE,
4489 EL_CHAR('S'), -1, -1
4492 Xalpha_t, TRUE, FALSE,
4493 EL_CHAR('T'), -1, -1
4496 Xalpha_u, TRUE, FALSE,
4497 EL_CHAR('U'), -1, -1
4500 Xalpha_v, TRUE, FALSE,
4501 EL_CHAR('V'), -1, -1
4504 Xalpha_w, TRUE, FALSE,
4505 EL_CHAR('W'), -1, -1
4508 Xalpha_x, TRUE, FALSE,
4509 EL_CHAR('X'), -1, -1
4512 Xalpha_y, TRUE, FALSE,
4513 EL_CHAR('Y'), -1, -1
4516 Xalpha_z, TRUE, FALSE,
4517 EL_CHAR('Z'), -1, -1
4520 Xalpha_arrow_e, TRUE, FALSE,
4521 EL_CHAR('>'), -1, -1
4524 Xalpha_arrow_w, TRUE, FALSE,
4525 EL_CHAR('<'), -1, -1
4528 Xalpha_copyr, TRUE, FALSE,
4529 EL_CHAR('©'), -1, -1
4532 Xalpha_copyr, TRUE, FALSE,
4533 EL_CHAR('©'), -1, -1
4537 Xboom_bug, FALSE, FALSE,
4538 EL_BUG, ACTION_EXPLODING, -1
4541 Xboom_bomb, FALSE, FALSE,
4542 EL_BOMB, ACTION_EXPLODING, -1
4545 Xboom_android, FALSE, FALSE,
4546 EL_EMC_ANDROID, ACTION_OTHER, -1
4549 Xboom_1, FALSE, FALSE,
4550 EL_DEFAULT, ACTION_EXPLODING, -1
4553 Xboom_2, FALSE, FALSE,
4554 EL_DEFAULT, ACTION_EXPLODING, -1
4557 Znormal, FALSE, FALSE,
4561 Zdynamite, FALSE, FALSE,
4565 Zplayer, FALSE, FALSE,
4569 ZBORDER, FALSE, FALSE,
4579 int map_element_RND_to_EM(int element_rnd)
4581 static unsigned short mapping_RND_to_EM[NUM_FILE_ELEMENTS];
4582 static boolean mapping_initialized = FALSE;
4584 if (!mapping_initialized)
4588 /* return "Xalpha_quest" for all undefined elements in mapping array */
4589 for (i = 0; i < NUM_FILE_ELEMENTS; i++)
4590 mapping_RND_to_EM[i] = Xalpha_quest;
4592 for (i = 0; mapping_EM_to_RND_list[i].element_em != -1; i++)
4593 if (mapping_EM_to_RND_list[i].is_rnd_to_em_mapping)
4594 mapping_RND_to_EM[mapping_EM_to_RND_list[i].element_rnd] =
4595 mapping_EM_to_RND_list[i].element_em;
4597 mapping_initialized = TRUE;
4600 if (element_rnd >= 0 && element_rnd < NUM_FILE_ELEMENTS)
4601 return mapping_RND_to_EM[element_rnd];
4603 Error(ERR_WARN, "invalid RND level element %d", element_rnd);
4608 int map_element_EM_to_RND(int element_em)
4610 static unsigned short mapping_EM_to_RND[TILE_MAX];
4611 static boolean mapping_initialized = FALSE;
4613 if (!mapping_initialized)
4617 /* return "EL_UNKNOWN" for all undefined elements in mapping array */
4618 for (i = 0; i < TILE_MAX; i++)
4619 mapping_EM_to_RND[i] = EL_UNKNOWN;
4621 for (i = 0; mapping_EM_to_RND_list[i].element_em != -1; i++)
4622 mapping_EM_to_RND[mapping_EM_to_RND_list[i].element_em] =
4623 mapping_EM_to_RND_list[i].element_rnd;
4625 mapping_initialized = TRUE;
4628 if (element_em >= 0 && element_em < TILE_MAX)
4629 return mapping_EM_to_RND[element_em];
4631 Error(ERR_WARN, "invalid EM level element %d", element_em);
4638 int map_element_RND_to_EM(int element_rnd)
4640 static unsigned short mapping_RND_to_EM[NUM_FILE_ELEMENTS];
4641 static boolean mapping_initialized = FALSE;
4648 mapping_RND_to_EM_list[] =
4650 { Xblank, EL_EMPTY },
4651 { Xstone, EL_ROCK },
4653 { Xbug_n, EL_BUG_UP },
4654 { Xbug_e, EL_BUG_RIGHT },
4655 { Xbug_s, EL_BUG_DOWN },
4656 { Xbug_w, EL_BUG_LEFT },
4657 { Xtank_n, EL_SPACESHIP_UP },
4658 { Xtank_e, EL_SPACESHIP_RIGHT },
4659 { Xtank_s, EL_SPACESHIP_DOWN },
4660 { Xtank_w, EL_SPACESHIP_LEFT },
4661 { Xandroid, EL_EMC_ANDROID },
4662 { Xandroid_1_n, EL_EMC_ANDROID_UP },
4663 { Xandroid_1_e, EL_EMC_ANDROID_RIGHT },
4664 { Xandroid_1_w, EL_EMC_ANDROID_LEFT },
4665 { Xandroid_1_s, EL_EMC_ANDROID_DOWN },
4666 { Xspring, EL_SPRING },
4667 { Xeater_n, EL_YAMYAM },
4668 { Xalien, EL_ROBOT },
4669 { Xemerald, EL_EMERALD },
4670 { Xdiamond, EL_DIAMOND },
4671 { Xdrip_fall, EL_AMOEBA_DROP },
4673 { Xballoon, EL_BALLOON },
4674 { Xgrass, EL_EMC_GRASS },
4676 { Xacid_ne, EL_ACID_POOL_TOPRIGHT },
4677 { Xacid_se, EL_ACID_POOL_BOTTOMRIGHT },
4678 { Xacid_s, EL_ACID_POOL_BOTTOM },
4679 { Xacid_sw, EL_ACID_POOL_BOTTOMLEFT },
4680 { Xacid_nw, EL_ACID_POOL_TOPLEFT },
4681 { Xacid_1, EL_ACID },
4682 { Xball_1, EL_EMC_MAGIC_BALL },
4683 { Xgrow_ns, EL_EMC_GROW },
4684 { Xwonderwall, EL_MAGIC_WALL },
4685 { Xamoeba_1, EL_AMOEBA_WET },
4686 { Xdoor_1, EL_EM_GATE_1 },
4687 { Xdoor_2, EL_EM_GATE_2 },
4688 { Xdoor_3, EL_EM_GATE_3 },
4689 { Xdoor_4, EL_EM_GATE_4 },
4690 { Xdoor_5, EL_EMC_GATE_5 },
4691 { Xdoor_6, EL_EMC_GATE_6 },
4692 { Xdoor_7, EL_EMC_GATE_7 },
4693 { Xdoor_8, EL_EMC_GATE_8 },
4694 { Xkey_1, EL_EM_KEY_1 },
4695 { Xkey_2, EL_EM_KEY_2 },
4696 { Xkey_3, EL_EM_KEY_3 },
4697 { Xkey_4, EL_EM_KEY_4 },
4698 { Xkey_5, EL_EMC_KEY_5 },
4699 { Xkey_6, EL_EMC_KEY_6 },
4700 { Xkey_7, EL_EMC_KEY_7 },
4701 { Xkey_8, EL_EMC_KEY_8 },
4702 { Xwind_n, EL_BALLOON_SWITCH_UP },
4703 { Xwind_e, EL_BALLOON_SWITCH_RIGHT },
4704 { Xwind_s, EL_BALLOON_SWITCH_DOWN },
4705 { Xwind_w, EL_BALLOON_SWITCH_LEFT },
4706 { Xwind_nesw, EL_BALLOON_SWITCH_ANY },
4707 { Xwind_stop, EL_BALLOON_SWITCH_NONE },
4708 { Xexit, EL_EXIT_CLOSED },
4709 { Xexit_1, EL_EXIT_OPEN },
4710 { Xdynamite, EL_DYNAMITE },
4711 { Xdynamite_1, EL_DYNAMITE_ACTIVE },
4712 { Xbumper, EL_EMC_BUMPER },
4713 { Xwheel, EL_ROBOT_WHEEL },
4714 { Xswitch, EL_UNKNOWN },
4715 { Xsand, EL_QUICKSAND_EMPTY },
4716 { Xsand_stone, EL_QUICKSAND_FULL },
4717 { Xplant, EL_EMC_PLANT },
4718 { Xlenses, EL_EMC_LENSES },
4719 { Xmagnify, EL_EMC_MAGNIFIER },
4720 { Xdripper, EL_UNKNOWN },
4721 { Xfake_blank, EL_INVISIBLE_WALL },
4722 { Xfake_grass, EL_INVISIBLE_SAND },
4723 { Xfake_door_1, EL_EM_GATE_1_GRAY },
4724 { Xfake_door_2, EL_EM_GATE_2_GRAY },
4725 { Xfake_door_3, EL_EM_GATE_3_GRAY },
4726 { Xfake_door_4, EL_EM_GATE_4_GRAY },
4727 { Xfake_door_5, EL_EMC_GATE_5_GRAY },
4728 { Xfake_door_6, EL_EMC_GATE_6_GRAY },
4729 { Xfake_door_7, EL_EMC_GATE_7_GRAY },
4730 { Xfake_door_8, EL_EMC_GATE_8_GRAY },
4731 { Xsteel_1, EL_STEELWALL },
4732 { Xsteel_2, EL_UNKNOWN },
4733 { Xsteel_3, EL_EMC_STEELWALL_1 },
4734 { Xsteel_4, EL_UNKNOWN },
4735 { Xwall_1, EL_WALL },
4736 { Xwall_2, EL_UNKNOWN },
4737 { Xwall_3, EL_UNKNOWN },
4738 { Xwall_4, EL_UNKNOWN },
4739 { Xround_wall_1, EL_WALL_SLIPPERY },
4740 { Xround_wall_2, EL_UNKNOWN },
4741 { Xround_wall_3, EL_UNKNOWN },
4742 { Xround_wall_4, EL_UNKNOWN },
4743 { Xdecor_1, EL_UNKNOWN },
4744 { Xdecor_2, EL_EMC_WALL_6 },
4745 { Xdecor_3, EL_EMC_WALL_4 },
4746 { Xdecor_4, EL_EMC_WALL_5 },
4747 { Xdecor_5, EL_EMC_WALL_7 },
4748 { Xdecor_6, EL_EMC_WALL_8 },
4749 { Xdecor_7, EL_UNKNOWN },
4750 { Xdecor_8, EL_EMC_WALL_1 },
4751 { Xdecor_9, EL_EMC_WALL_2 },
4752 { Xdecor_10, EL_EMC_WALL_3 },
4753 { Xdecor_11, EL_UNKNOWN },
4754 { Xdecor_12, EL_UNKNOWN },
4755 { Xalpha_0, EL_CHAR('0') },
4756 { Xalpha_1, EL_CHAR('1') },
4757 { Xalpha_2, EL_CHAR('2') },
4758 { Xalpha_3, EL_CHAR('3') },
4759 { Xalpha_4, EL_CHAR('4') },
4760 { Xalpha_5, EL_CHAR('5') },
4761 { Xalpha_6, EL_CHAR('6') },
4762 { Xalpha_7, EL_CHAR('7') },
4763 { Xalpha_8, EL_CHAR('8') },
4764 { Xalpha_9, EL_CHAR('9') },
4765 { Xalpha_excla, EL_CHAR('!') },
4766 { Xalpha_quote, EL_CHAR('"') },
4767 { Xalpha_comma, EL_CHAR(',') },
4768 { Xalpha_minus, EL_CHAR('-') },
4769 { Xalpha_perio, EL_CHAR('.') },
4770 { Xalpha_colon, EL_CHAR(':') },
4771 { Xalpha_quest, EL_CHAR('?') },
4772 { Xalpha_a, EL_CHAR('A') },
4773 { Xalpha_b, EL_CHAR('B') },
4774 { Xalpha_c, EL_CHAR('C') },
4775 { Xalpha_d, EL_CHAR('D') },
4776 { Xalpha_e, EL_CHAR('E') },
4777 { Xalpha_f, EL_CHAR('F') },
4778 { Xalpha_g, EL_CHAR('G') },
4779 { Xalpha_h, EL_CHAR('H') },
4780 { Xalpha_i, EL_CHAR('I') },
4781 { Xalpha_j, EL_CHAR('J') },
4782 { Xalpha_k, EL_CHAR('K') },
4783 { Xalpha_l, EL_CHAR('L') },
4784 { Xalpha_m, EL_CHAR('M') },
4785 { Xalpha_n, EL_CHAR('N') },
4786 { Xalpha_o, EL_CHAR('O') },
4787 { Xalpha_p, EL_CHAR('P') },
4788 { Xalpha_q, EL_CHAR('Q') },
4789 { Xalpha_r, EL_CHAR('R') },
4790 { Xalpha_s, EL_CHAR('S') },
4791 { Xalpha_t, EL_CHAR('T') },
4792 { Xalpha_u, EL_CHAR('U') },
4793 { Xalpha_v, EL_CHAR('V') },
4794 { Xalpha_w, EL_CHAR('W') },
4795 { Xalpha_x, EL_CHAR('X') },
4796 { Xalpha_y, EL_CHAR('Y') },
4797 { Xalpha_z, EL_CHAR('Z') },
4798 { Xalpha_arrow_e, EL_CHAR('>') },
4799 { Xalpha_arrow_w, EL_CHAR('<') },
4800 { Xalpha_copyr, EL_CHAR('©') },
4802 { Zplayer, EL_PLAYER_1 },
4803 { Zplayer, EL_PLAYER_2 },
4804 { Zplayer, EL_PLAYER_3 },
4805 { Zplayer, EL_PLAYER_4 },
4807 { ZBORDER, EL_EMC_LEVEL_BORDER },
4812 if (!mapping_initialized)
4816 /* return "Xalpha_quest" for all undefined elements in mapping array */
4817 for (i = 0; i < NUM_FILE_ELEMENTS; i++)
4818 mapping_RND_to_EM[i] = Xalpha_quest;
4820 for (i = 0; mapping_RND_to_EM_list[i].element_rnd != -1; i++)
4821 mapping_RND_to_EM[mapping_RND_to_EM_list[i].element_rnd] =
4822 mapping_RND_to_EM_list[i].element_em;
4824 mapping_initialized = TRUE;
4827 if (element_rnd >= 0 && element_rnd < NUM_FILE_ELEMENTS)
4828 return mapping_RND_to_EM[element_rnd];
4830 Error(ERR_WARN, "invalid RND level element %d", element_rnd);
4835 int map_element_EM_to_RND(int element_em)
4837 static unsigned short mapping_EM_to_RND[TILE_MAX];
4838 static boolean mapping_initialized = FALSE;
4845 mapping_EM_to_RND_list[] =
4847 { Xblank, EL_EMPTY },
4848 { Yacid_splash_eB, EL_EMPTY },
4849 { Yacid_splash_wB, EL_EMPTY },
4851 #ifdef EM_ENGINE_BAD_ROLL
4852 { Xstone_force_e, EL_ROCK },
4853 { Xstone_force_w, EL_ROCK },
4854 { Xnut_force_e, EL_NUT },
4855 { Xnut_force_w, EL_NUT },
4856 { Xspring_force_e, EL_SPRING },
4857 { Xspring_force_w, EL_SPRING },
4858 { Xemerald_force_e, EL_EMERALD },
4859 { Xemerald_force_w, EL_EMERALD },
4860 { Xdiamond_force_e, EL_DIAMOND },
4861 { Xdiamond_force_w, EL_DIAMOND },
4862 { Xbomb_force_e, EL_BOMB },
4863 { Xbomb_force_w, EL_BOMB },
4866 { Xstone, EL_ROCK },
4867 { Xstone_pause, EL_ROCK },
4868 { Xstone_fall, EL_ROCK },
4869 { Ystone_s, EL_ROCK },
4870 { Ystone_sB, EL_ROCK },
4871 { Ystone_e, EL_ROCK },
4872 { Ystone_eB, EL_ROCK },
4873 { Ystone_w, EL_ROCK },
4874 { Ystone_wB, EL_ROCK },
4876 { Xnut_pause, EL_NUT },
4877 { Xnut_fall, EL_NUT },
4879 { Ynut_sB, EL_NUT },
4881 { Ynut_eB, EL_NUT },
4883 { Ynut_wB, EL_NUT },
4884 { Xbug_n, EL_BUG_UP },
4885 { Xbug_e, EL_BUG_RIGHT },
4886 { Xbug_s, EL_BUG_DOWN },
4887 { Xbug_w, EL_BUG_LEFT },
4888 { Xbug_gon, EL_BUG_UP },
4889 { Xbug_goe, EL_BUG_RIGHT },
4890 { Xbug_gos, EL_BUG_DOWN },
4891 { Xbug_gow, EL_BUG_LEFT },
4892 { Ybug_n, EL_BUG_UP },
4893 { Ybug_nB, EL_BUG_UP },
4894 { Ybug_e, EL_BUG_RIGHT },
4895 { Ybug_eB, EL_BUG_RIGHT },
4896 { Ybug_s, EL_BUG_DOWN },
4897 { Ybug_sB, EL_BUG_DOWN },
4898 { Ybug_w, EL_BUG_LEFT },
4899 { Ybug_wB, EL_BUG_LEFT },
4900 { Ybug_w_n, EL_BUG_UP },
4901 { Ybug_n_e, EL_BUG_RIGHT },
4902 { Ybug_e_s, EL_BUG_DOWN },
4903 { Ybug_s_w, EL_BUG_LEFT },
4904 { Ybug_e_n, EL_BUG_UP },
4905 { Ybug_s_e, EL_BUG_RIGHT },
4906 { Ybug_w_s, EL_BUG_DOWN },
4907 { Ybug_n_w, EL_BUG_LEFT },
4908 { Ybug_stone, EL_ROCK },
4909 { Ybug_spring, EL_SPRING },
4910 { Xtank_n, EL_SPACESHIP_UP },
4911 { Xtank_e, EL_SPACESHIP_RIGHT },
4912 { Xtank_s, EL_SPACESHIP_DOWN },
4913 { Xtank_w, EL_SPACESHIP_LEFT },
4914 { Xtank_gon, EL_SPACESHIP_UP },
4915 { Xtank_goe, EL_SPACESHIP_RIGHT },
4916 { Xtank_gos, EL_SPACESHIP_DOWN },
4917 { Xtank_gow, EL_SPACESHIP_LEFT },
4918 { Ytank_n, EL_SPACESHIP_UP },
4919 { Ytank_nB, EL_SPACESHIP_UP },
4920 { Ytank_e, EL_SPACESHIP_RIGHT },
4921 { Ytank_eB, EL_SPACESHIP_RIGHT },
4922 { Ytank_s, EL_SPACESHIP_DOWN },
4923 { Ytank_sB, EL_SPACESHIP_DOWN },
4924 { Ytank_w, EL_SPACESHIP_LEFT },
4925 { Ytank_wB, EL_SPACESHIP_LEFT },
4926 { Ytank_w_n, EL_SPACESHIP_UP },
4927 { Ytank_n_e, EL_SPACESHIP_RIGHT },
4928 { Ytank_e_s, EL_SPACESHIP_DOWN },
4929 { Ytank_s_w, EL_SPACESHIP_LEFT },
4930 { Ytank_e_n, EL_SPACESHIP_UP },
4931 { Ytank_s_e, EL_SPACESHIP_RIGHT },
4932 { Ytank_w_s, EL_SPACESHIP_DOWN },
4933 { Ytank_n_w, EL_SPACESHIP_LEFT },
4934 { Ytank_stone, EL_ROCK },
4935 { Ytank_spring, EL_SPRING },
4936 { Xandroid, EL_EMC_ANDROID },
4937 { Xandroid_1_n, EL_EMC_ANDROID_UP },
4938 { Xandroid_2_n, EL_EMC_ANDROID_UP },
4939 { Xandroid_1_e, EL_EMC_ANDROID_RIGHT },
4940 { Xandroid_2_e, EL_EMC_ANDROID_RIGHT },
4941 { Xandroid_1_w, EL_EMC_ANDROID_LEFT },
4942 { Xandroid_2_w, EL_EMC_ANDROID_LEFT },
4943 { Xandroid_1_s, EL_EMC_ANDROID_DOWN },
4944 { Xandroid_2_s, EL_EMC_ANDROID_DOWN },
4945 { Yandroid_n, EL_EMC_ANDROID_UP },
4946 { Yandroid_nB, EL_EMC_ANDROID_UP },
4947 { Yandroid_ne, EL_EMC_ANDROID_RIGHT_UP },
4948 { Yandroid_neB, EL_EMC_ANDROID_RIGHT_UP },
4949 { Yandroid_e, EL_EMC_ANDROID_RIGHT },
4950 { Yandroid_eB, EL_EMC_ANDROID_RIGHT },
4951 { Yandroid_se, EL_EMC_ANDROID_RIGHT_DOWN },
4952 { Yandroid_seB, EL_EMC_ANDROID_RIGHT_DOWN },
4953 { Yandroid_s, EL_EMC_ANDROID_DOWN },
4954 { Yandroid_sB, EL_EMC_ANDROID_DOWN },
4955 { Yandroid_sw, EL_EMC_ANDROID_LEFT_DOWN },
4956 { Yandroid_swB, EL_EMC_ANDROID_LEFT_DOWN },
4957 { Yandroid_w, EL_EMC_ANDROID_LEFT },
4958 { Yandroid_wB, EL_EMC_ANDROID_LEFT },
4959 { Yandroid_nw, EL_EMC_ANDROID_LEFT_UP },
4960 { Yandroid_nwB, EL_EMC_ANDROID_LEFT_UP },
4961 { Xspring, EL_SPRING },
4962 { Xspring_pause, EL_SPRING },
4963 { Xspring_e, EL_SPRING },
4964 { Xspring_w, EL_SPRING },
4965 { Xspring_fall, EL_SPRING },
4966 { Yspring_s, EL_SPRING },
4967 { Yspring_sB, EL_SPRING },
4968 { Yspring_e, EL_SPRING },
4969 { Yspring_eB, EL_SPRING },
4970 { Yspring_w, EL_SPRING },
4971 { Yspring_wB, EL_SPRING },
4972 { Yspring_kill_e, EL_SPRING },
4973 { Yspring_kill_eB, EL_SPRING },
4974 { Yspring_kill_w, EL_SPRING },
4975 { Yspring_kill_wB, EL_SPRING },
4976 { Xeater_n, EL_YAMYAM },
4977 { Xeater_e, EL_YAMYAM },
4978 { Xeater_w, EL_YAMYAM },
4979 { Xeater_s, EL_YAMYAM },
4980 { Yeater_n, EL_YAMYAM },
4981 { Yeater_nB, EL_YAMYAM },
4982 { Yeater_e, EL_YAMYAM },
4983 { Yeater_eB, EL_YAMYAM },
4984 { Yeater_s, EL_YAMYAM },
4985 { Yeater_sB, EL_YAMYAM },
4986 { Yeater_w, EL_YAMYAM },
4987 { Yeater_wB, EL_YAMYAM },
4988 { Yeater_stone, EL_ROCK },
4989 { Yeater_spring, EL_SPRING },
4990 { Xalien, EL_ROBOT },
4991 { Xalien_pause, EL_ROBOT },
4992 { Yalien_n, EL_ROBOT },
4993 { Yalien_nB, EL_ROBOT },
4994 { Yalien_e, EL_ROBOT },
4995 { Yalien_eB, EL_ROBOT },
4996 { Yalien_s, EL_ROBOT },
4997 { Yalien_sB, EL_ROBOT },
4998 { Yalien_w, EL_ROBOT },
4999 { Yalien_wB, EL_ROBOT },
5000 { Yalien_stone, EL_ROCK },
5001 { Yalien_spring, EL_SPRING },
5002 { Xemerald, EL_EMERALD },
5003 { Xemerald_pause, EL_EMERALD },
5004 { Xemerald_fall, EL_EMERALD },
5005 { Xemerald_shine, EL_EMERALD },
5006 { Yemerald_s, EL_EMERALD },
5007 { Yemerald_sB, EL_EMERALD },
5008 { Yemerald_e, EL_EMERALD },
5009 { Yemerald_eB, EL_EMERALD },
5010 { Yemerald_w, EL_EMERALD },
5011 { Yemerald_wB, EL_EMERALD },
5012 { Yemerald_eat, EL_EMERALD },
5013 { Yemerald_stone, EL_ROCK },
5014 { Xdiamond, EL_DIAMOND },
5015 { Xdiamond_pause, EL_DIAMOND },
5016 { Xdiamond_fall, EL_DIAMOND },
5017 { Xdiamond_shine, EL_DIAMOND },
5018 { Ydiamond_s, EL_DIAMOND },
5019 { Ydiamond_sB, EL_DIAMOND },
5020 { Ydiamond_e, EL_DIAMOND },
5021 { Ydiamond_eB, EL_DIAMOND },
5022 { Ydiamond_w, EL_DIAMOND },
5023 { Ydiamond_wB, EL_DIAMOND },
5024 { Ydiamond_eat, EL_DIAMOND },
5025 { Ydiamond_stone, EL_ROCK },
5026 { Xdrip_fall, EL_AMOEBA_DROP },
5027 { Xdrip_stretch, EL_AMOEBA_DROP },
5028 { Xdrip_stretchB, EL_AMOEBA_DROP },
5029 { Xdrip_eat, EL_AMOEBA_DROP },
5030 { Ydrip_s1, EL_AMOEBA_DROP },
5031 { Ydrip_s1B, EL_AMOEBA_DROP },
5032 { Ydrip_s2, EL_AMOEBA_DROP },
5033 { Ydrip_s2B, EL_AMOEBA_DROP },
5035 { Xbomb_pause, EL_BOMB },
5036 { Xbomb_fall, EL_BOMB },
5037 { Ybomb_s, EL_BOMB },
5038 { Ybomb_sB, EL_BOMB },
5039 { Ybomb_e, EL_BOMB },
5040 { Ybomb_eB, EL_BOMB },
5041 { Ybomb_w, EL_BOMB },
5042 { Ybomb_wB, EL_BOMB },
5043 { Ybomb_eat, EL_BOMB },
5044 { Xballoon, EL_BALLOON },
5045 { Yballoon_n, EL_BALLOON },
5046 { Yballoon_nB, EL_BALLOON },
5047 { Yballoon_e, EL_BALLOON },
5048 { Yballoon_eB, EL_BALLOON },
5049 { Yballoon_s, EL_BALLOON },
5050 { Yballoon_sB, EL_BALLOON },
5051 { Yballoon_w, EL_BALLOON },
5052 { Yballoon_wB, EL_BALLOON },
5053 { Xgrass, EL_SAND },
5054 { Ygrass_nB, EL_SAND },
5055 { Ygrass_eB, EL_SAND },
5056 { Ygrass_sB, EL_SAND },
5057 { Ygrass_wB, EL_SAND },
5059 { Ydirt_nB, EL_SAND },
5060 { Ydirt_eB, EL_SAND },
5061 { Ydirt_sB, EL_SAND },
5062 { Ydirt_wB, EL_SAND },
5063 { Xacid_ne, EL_ACID_POOL_TOPRIGHT },
5064 { Xacid_se, EL_ACID_POOL_BOTTOMRIGHT },
5065 { Xacid_s, EL_ACID_POOL_BOTTOM },
5066 { Xacid_sw, EL_ACID_POOL_BOTTOMLEFT },
5067 { Xacid_nw, EL_ACID_POOL_TOPLEFT },
5068 { Xacid_1, EL_ACID },
5069 { Xacid_2, EL_ACID },
5070 { Xacid_3, EL_ACID },
5071 { Xacid_4, EL_ACID },
5072 { Xacid_5, EL_ACID },
5073 { Xacid_6, EL_ACID },
5074 { Xacid_7, EL_ACID },
5075 { Xacid_8, EL_ACID },
5076 { Xball_1, EL_EMC_MAGIC_BALL },
5077 { Xball_1B, EL_EMC_MAGIC_BALL },
5078 { Xball_2, EL_EMC_MAGIC_BALL },
5079 { Xball_2B, EL_EMC_MAGIC_BALL },
5080 { Yball_eat, EL_EMC_MAGIC_BALL },
5081 { Xgrow_ns, EL_EMC_GROW },
5082 { Ygrow_ns_eat, EL_EMC_GROW },
5083 { Xgrow_ew, EL_EMC_GROW },
5084 { Ygrow_ew_eat, EL_EMC_GROW },
5085 { Xwonderwall, EL_MAGIC_WALL },
5086 { XwonderwallB, EL_MAGIC_WALL },
5087 { Xamoeba_1, EL_AMOEBA_WET },
5088 { Xamoeba_2, EL_AMOEBA_WET },
5089 { Xamoeba_3, EL_AMOEBA_WET },
5090 { Xamoeba_4, EL_AMOEBA_WET },
5091 { Xamoeba_5, EL_AMOEBA_WET },
5092 { Xamoeba_6, EL_AMOEBA_WET },
5093 { Xamoeba_7, EL_AMOEBA_WET },
5094 { Xamoeba_8, EL_AMOEBA_WET },
5095 { Xdoor_1, EL_EM_GATE_1 },
5096 { Xdoor_2, EL_EM_GATE_2 },
5097 { Xdoor_3, EL_EM_GATE_3 },
5098 { Xdoor_4, EL_EM_GATE_4 },
5099 { Xdoor_5, EL_EMC_GATE_5 },
5100 { Xdoor_6, EL_EMC_GATE_6 },
5101 { Xdoor_7, EL_EMC_GATE_7 },
5102 { Xdoor_8, EL_EMC_GATE_8 },
5103 { Xkey_1, EL_EM_KEY_1 },
5104 { Xkey_2, EL_EM_KEY_2 },
5105 { Xkey_3, EL_EM_KEY_3 },
5106 { Xkey_4, EL_EM_KEY_4 },
5107 { Xkey_5, EL_EMC_KEY_5 },
5108 { Xkey_6, EL_EMC_KEY_6 },
5109 { Xkey_7, EL_EMC_KEY_7 },
5110 { Xkey_8, EL_EMC_KEY_8 },
5111 { Xwind_n, EL_BALLOON_SWITCH_UP },
5112 { Xwind_e, EL_BALLOON_SWITCH_RIGHT },
5113 { Xwind_s, EL_BALLOON_SWITCH_DOWN },
5114 { Xwind_w, EL_BALLOON_SWITCH_LEFT },
5115 { Xwind_nesw, EL_BALLOON_SWITCH_ANY },
5116 { Xwind_stop, EL_BALLOON_SWITCH_NONE },
5117 { Xexit, EL_EXIT_CLOSED },
5118 { Xexit_1, EL_EXIT_OPEN },
5119 { Xexit_2, EL_EXIT_OPEN },
5120 { Xexit_3, EL_EXIT_OPEN },
5121 { Xdynamite, EL_DYNAMITE },
5122 { Ydynamite_eat, EL_DYNAMITE },
5123 { Xdynamite_1, EL_DYNAMITE_ACTIVE },
5124 { Xdynamite_2, EL_DYNAMITE_ACTIVE },
5125 { Xdynamite_3, EL_DYNAMITE_ACTIVE },
5126 { Xdynamite_4, EL_DYNAMITE_ACTIVE },
5127 { Xbumper, EL_EMC_BUMPER },
5128 { XbumperB, EL_EMC_BUMPER },
5129 { Xwheel, EL_ROBOT_WHEEL },
5130 { XwheelB, EL_ROBOT_WHEEL },
5131 { Xswitch, EL_UNKNOWN },
5132 { XswitchB, EL_UNKNOWN },
5133 { Xsand, EL_QUICKSAND_EMPTY },
5134 { Xsand_stone, EL_QUICKSAND_FULL },
5135 { Xsand_stonein_1, EL_QUICKSAND_FULL },
5136 { Xsand_stonein_2, EL_QUICKSAND_FULL },
5137 { Xsand_stonein_3, EL_QUICKSAND_FULL },
5138 { Xsand_stonein_4, EL_QUICKSAND_FULL },
5139 { Xsand_stonesand_1, EL_QUICKSAND_FULL },
5140 { Xsand_stonesand_2, EL_QUICKSAND_FULL },
5141 { Xsand_stonesand_3, EL_QUICKSAND_FULL },
5142 { Xsand_stonesand_4, EL_QUICKSAND_FULL },
5143 { Xsand_stoneout_1, EL_QUICKSAND_FULL },
5144 { Xsand_stoneout_2, EL_QUICKSAND_FULL },
5145 { Xsand_sandstone_1, EL_QUICKSAND_FULL },
5146 { Xsand_sandstone_2, EL_QUICKSAND_FULL },
5147 { Xsand_sandstone_3, EL_QUICKSAND_FULL },
5148 { Xsand_sandstone_4, EL_QUICKSAND_FULL },
5149 { Xplant, EL_EMC_PLANT },
5150 { Yplant, EL_EMC_PLANT },
5151 { Xlenses, EL_EMC_LENSES },
5152 { Xmagnify, EL_EMC_MAGNIFIER },
5153 { Xdripper, EL_UNKNOWN },
5154 { XdripperB, EL_UNKNOWN },
5155 { Xfake_blank, EL_INVISIBLE_WALL },
5156 { Xfake_blankB, EL_INVISIBLE_WALL },
5157 { Xfake_grass, EL_INVISIBLE_SAND },
5158 { Xfake_grassB, EL_INVISIBLE_SAND },
5159 { Xfake_door_1, EL_EM_GATE_1_GRAY },
5160 { Xfake_door_2, EL_EM_GATE_2_GRAY },
5161 { Xfake_door_3, EL_EM_GATE_3_GRAY },
5162 { Xfake_door_4, EL_EM_GATE_4_GRAY },
5163 { Xfake_door_5, EL_EMC_GATE_5_GRAY },
5164 { Xfake_door_6, EL_EMC_GATE_6_GRAY },
5165 { Xfake_door_7, EL_EMC_GATE_7_GRAY },
5166 { Xfake_door_8, EL_EMC_GATE_8_GRAY },
5167 { Xsteel_1, EL_STEELWALL },
5168 { Xsteel_2, EL_UNKNOWN },
5169 { Xsteel_3, EL_EMC_STEELWALL_1 },
5170 { Xsteel_4, EL_UNKNOWN },
5171 { Xwall_1, EL_WALL },
5172 { Xwall_2, EL_UNKNOWN },
5173 { Xwall_3, EL_UNKNOWN },
5174 { Xwall_4, EL_UNKNOWN },
5175 { Xround_wall_1, EL_WALL_SLIPPERY },
5176 { Xround_wall_2, EL_UNKNOWN },
5177 { Xround_wall_3, EL_UNKNOWN },
5178 { Xround_wall_4, EL_UNKNOWN },
5179 { Xdecor_1, EL_UNKNOWN },
5180 { Xdecor_2, EL_EMC_WALL_6 },
5181 { Xdecor_3, EL_EMC_WALL_4 },
5182 { Xdecor_4, EL_EMC_WALL_5 },
5183 { Xdecor_5, EL_EMC_WALL_7 },
5184 { Xdecor_6, EL_EMC_WALL_8 },
5185 { Xdecor_7, EL_UNKNOWN },
5186 { Xdecor_8, EL_EMC_WALL_1 },
5187 { Xdecor_9, EL_EMC_WALL_2 },
5188 { Xdecor_10, EL_EMC_WALL_3 },
5189 { Xdecor_11, EL_UNKNOWN },
5190 { Xdecor_12, EL_UNKNOWN },
5191 { Xalpha_0, EL_CHAR('0') },
5192 { Xalpha_1, EL_CHAR('1') },
5193 { Xalpha_2, EL_CHAR('2') },
5194 { Xalpha_3, EL_CHAR('3') },
5195 { Xalpha_4, EL_CHAR('4') },
5196 { Xalpha_5, EL_CHAR('5') },
5197 { Xalpha_6, EL_CHAR('6') },
5198 { Xalpha_7, EL_CHAR('7') },
5199 { Xalpha_8, EL_CHAR('8') },
5200 { Xalpha_9, EL_CHAR('9') },
5201 { Xalpha_excla, EL_CHAR('!') },
5202 { Xalpha_quote, EL_CHAR('"') },
5203 { Xalpha_comma, EL_CHAR(',') },
5204 { Xalpha_minus, EL_CHAR('-') },
5205 { Xalpha_perio, EL_CHAR('.') },
5206 { Xalpha_colon, EL_CHAR(':') },
5207 { Xalpha_quest, EL_CHAR('?') },
5208 { Xalpha_a, EL_CHAR('A') },
5209 { Xalpha_b, EL_CHAR('B') },
5210 { Xalpha_c, EL_CHAR('C') },
5211 { Xalpha_d, EL_CHAR('D') },
5212 { Xalpha_e, EL_CHAR('E') },
5213 { Xalpha_f, EL_CHAR('F') },
5214 { Xalpha_g, EL_CHAR('G') },
5215 { Xalpha_h, EL_CHAR('H') },
5216 { Xalpha_i, EL_CHAR('I') },
5217 { Xalpha_j, EL_CHAR('J') },
5218 { Xalpha_k, EL_CHAR('K') },
5219 { Xalpha_l, EL_CHAR('L') },
5220 { Xalpha_m, EL_CHAR('M') },
5221 { Xalpha_n, EL_CHAR('N') },
5222 { Xalpha_o, EL_CHAR('O') },
5223 { Xalpha_p, EL_CHAR('P') },
5224 { Xalpha_q, EL_CHAR('Q') },
5225 { Xalpha_r, EL_CHAR('R') },
5226 { Xalpha_s, EL_CHAR('S') },
5227 { Xalpha_t, EL_CHAR('T') },
5228 { Xalpha_u, EL_CHAR('U') },
5229 { Xalpha_v, EL_CHAR('V') },
5230 { Xalpha_w, EL_CHAR('W') },
5231 { Xalpha_x, EL_CHAR('X') },
5232 { Xalpha_y, EL_CHAR('Y') },
5233 { Xalpha_z, EL_CHAR('Z') },
5234 { Xalpha_arrow_e, EL_CHAR('>') },
5235 { Xalpha_arrow_w, EL_CHAR('<') },
5236 { Xalpha_copyr, EL_CHAR('©') },
5238 { Zplayer, EL_PLAYER_1 },
5240 { ZBORDER, EL_EMC_LEVEL_BORDER },
5245 if (!mapping_initialized)
5249 /* return "EL_UNKNOWN" for all undefined elements in mapping array */
5250 for (i = 0; i < TILE_MAX; i++)
5251 mapping_EM_to_RND[i] = EL_UNKNOWN;
5253 for (i = 0; mapping_EM_to_RND_list[i].element_em != -1; i++)
5254 mapping_EM_to_RND[mapping_EM_to_RND_list[i].element_em] =
5255 mapping_EM_to_RND_list[i].element_rnd;
5257 mapping_initialized = TRUE;
5260 if (element_em >= 0 && element_em < TILE_MAX)
5261 return mapping_EM_to_RND[element_em];
5263 Error(ERR_WARN, "invalid EM level element %d", element_em);
5270 int get_next_element(int element)
5274 case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL;
5275 case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY;
5276 case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL;
5277 case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_ACTIVE;
5278 case EL_BD_MAGIC_WALL_FILLING: return EL_BD_MAGIC_WALL_FULL;
5279 case EL_BD_MAGIC_WALL_EMPTYING: return EL_BD_MAGIC_WALL_ACTIVE;
5280 case EL_AMOEBA_DROPPING: return EL_AMOEBA_WET;
5282 default: return element;
5286 int el_act_dir2img(int element, int action, int direction)
5288 element = GFX_ELEMENT(element);
5289 direction = MV_DIR_BIT(direction); /* default: MV_NO_MOVING => MV_DOWN */
5291 return element_info[element].direction_graphic[action][direction];
5294 static int el_act_dir2crm(int element, int action, int direction)
5296 element = GFX_ELEMENT(element);
5297 direction = MV_DIR_BIT(direction); /* default: MV_NO_MOVING => MV_DOWN */
5299 return element_info[element].direction_crumbled[action][direction];
5302 int el_act2img(int element, int action)
5304 element = GFX_ELEMENT(element);
5306 return element_info[element].graphic[action];
5309 int el_act2crm(int element, int action)
5311 element = GFX_ELEMENT(element);
5313 return element_info[element].crumbled[action];
5316 int el_dir2img(int element, int direction)
5318 element = GFX_ELEMENT(element);
5320 return el_act_dir2img(element, ACTION_DEFAULT, direction);
5323 int el2baseimg(int element)
5325 return element_info[element].graphic[ACTION_DEFAULT];
5328 int el2img(int element)
5330 element = GFX_ELEMENT(element);
5332 return element_info[element].graphic[ACTION_DEFAULT];
5335 int el2edimg(int element)
5337 element = GFX_ELEMENT(element);
5339 return element_info[element].special_graphic[GFX_SPECIAL_ARG_EDITOR];
5342 int el2preimg(int element)
5344 element = GFX_ELEMENT(element);
5346 return element_info[element].special_graphic[GFX_SPECIAL_ARG_PREVIEW];
5349 int getGameFrameDelay_EM(int native_em_game_frame_delay)
5351 return (GameFrameDelay == GAME_FRAME_DELAY ? native_em_game_frame_delay :
5355 unsigned int InitRND(long seed)
5357 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
5358 return InitEngineRND_EM(seed);
5360 return InitEngineRND(seed);
5363 void InitGraphicInfo_EM(void)
5365 int mapping_EM_to_RND_element[TILE_MAX];
5366 int mapping_EM_to_RND_action[TILE_MAX];
5367 int mapping_EM_to_RND_direction[TILE_MAX];
5368 boolean mapping_EM_to_RND_backside[TILE_MAX];
5371 /* return "EL_UNKNOWN" for all undefined elements in mapping array */
5372 for (i = 0; i < TILE_MAX; i++)
5374 mapping_EM_to_RND_element[i] = EL_UNKNOWN;
5375 mapping_EM_to_RND_backside[i] = FALSE;
5376 mapping_EM_to_RND_action[i] = ACTION_DEFAULT;
5377 mapping_EM_to_RND_direction[i] = MV_NO_MOVING;
5380 for (i = 0; mapping_EM_to_RND_list[i].element_em != -1; i++)
5382 int e = mapping_EM_to_RND_list[i].element_em;
5384 mapping_EM_to_RND_element[e] = mapping_EM_to_RND_list[i].element_rnd;
5385 mapping_EM_to_RND_backside[e] = mapping_EM_to_RND_list[i].is_backside;
5387 if (mapping_EM_to_RND_list[i].action != -1)
5388 mapping_EM_to_RND_action[e] = mapping_EM_to_RND_list[i].action;
5390 if (mapping_EM_to_RND_list[i].direction != -1)
5391 mapping_EM_to_RND_direction[e] = 1<< mapping_EM_to_RND_list[i].direction;
5394 for (i = 0; i < TILE_MAX; i++)
5396 int element = mapping_EM_to_RND_element[i];
5397 int action = mapping_EM_to_RND_action[i];
5398 int direction = mapping_EM_to_RND_direction[i];
5399 int backside = mapping_EM_to_RND_backside[i];
5400 boolean action_removing = (action == ACTION_DIGGING ||
5401 action == ACTION_SNAPPING ||
5402 action == ACTION_COLLECTING);
5403 boolean action_exploding = ((action == ACTION_EXPLODING ||
5404 action == ACTION_SMASHED_BY_ROCK ||
5405 action == ACTION_SMASHED_BY_SPRING) &&
5406 element != EL_DIAMOND);
5407 boolean action_active = (action == ACTION_ACTIVE);
5408 boolean action_other = (action == ACTION_OTHER);
5410 for (j = 0; j < 8; j++)
5412 int effective_element = (j < 7 ? element :
5413 i == Ynut_sB ? element :
5414 i == Xdrip_stretch ? element :
5415 i == Xdrip_stretchB ? element :
5416 i == Ydrip_s1 ? element :
5417 i == Ydrip_s1B ? element :
5418 i == Xball_1B ? element :
5419 i == Xball_2 ? element :
5420 i == Xball_2B ? element :
5421 i == Yball_eat ? element :
5422 i == Yspring_kill_e ? EL_SPRING :
5423 i == Yspring_kill_w ? EL_SPRING :
5424 i == Yemerald_stone ? EL_EMERALD :
5425 i == Ydiamond_stone ? EL_ROCK :
5426 backside ? EL_EMPTY :
5427 action_removing ? EL_EMPTY :
5429 int effective_action = (j < 7 ? action :
5430 i == Ynut_sB ? action :
5431 i == Xdrip_stretch ? action :
5432 i == Xdrip_stretchB ? action :
5433 i == Ydrip_s1 ? action :
5434 i == Ydrip_s1B ? action :
5435 i == Xball_1B ? action :
5436 i == Xball_2 ? action :
5437 i == Xball_2B ? action :
5438 i == Yball_eat ? action :
5439 i == Xsand_stonein_1 ? action :
5440 i == Xsand_stonein_2 ? action :
5441 i == Xsand_stonein_3 ? action :
5442 i == Xsand_stonein_4 ? action :
5443 i == Xsand_stoneout_1 ? action :
5444 i == Xsand_stoneout_2 ? action :
5445 i == Xboom_android ? ACTION_EXPLODING :
5446 action_exploding ? ACTION_EXPLODING :
5447 action_active ? action :
5448 action_other ? action :
5450 int graphic = (direction == MV_NO_MOVING ?
5451 el_act2img(effective_element, effective_action) :
5452 el_act_dir2img(effective_element, effective_action,
5454 struct GraphicInfo *g = &graphic_info[graphic];
5455 struct GraphicInfo_EM *g_em = &graphic_info_em[i][7 - j];
5458 int sync_frame = (i == Xdrip_stretch ? 7 :
5459 i == Xdrip_stretchB ? 7 :
5460 i == Ydrip_s2 ? j + 8 :
5461 i == Ydrip_s2B ? j + 8 :
5471 i == Xball_2B ? j + 8 :
5472 i == Yball_eat ? j + 1 :
5473 i == Xamoeba_1 ? 0 :
5474 i == Xamoeba_2 ? 1 :
5475 i == Xamoeba_3 ? 2 :
5476 i == Xamoeba_4 ? 3 :
5477 i == Xamoeba_5 ? 0 :
5478 i == Xamoeba_6 ? 1 :
5479 i == Xamoeba_7 ? 2 :
5480 i == Xamoeba_8 ? 3 :
5481 i == Xexit_2 ? j + 8 :
5482 i == Xexit_3 ? j + 16 :
5483 i == Xdynamite_1 ? 0 :
5484 i == Xdynamite_2 ? 2 :
5485 i == Xdynamite_3 ? 4 :
5486 i == Xdynamite_4 ? 6 :
5487 i == Xsand_stonein_1 ? j + 1 :
5488 i == Xsand_stonein_2 ? j + 9 :
5489 i == Xsand_stonein_3 ? j + 17 :
5490 i == Xsand_stonein_4 ? j + 25 :
5491 i == Xsand_stoneout_1 && j == 0 ? 1 :
5492 i == Xsand_stoneout_1 && j == 1 ? 1 :
5493 i == Xsand_stoneout_1 && j == 2 ? 2 :
5494 i == Xsand_stoneout_1 && j == 3 ? 4 :
5495 i == Xsand_stoneout_1 && j == 4 ? 4 :
5496 i == Xsand_stoneout_1 && j == 5 ? 6 :
5497 i == Xsand_stoneout_1 && j == 6 ? 8 :
5498 i == Xsand_stoneout_1 && j == 7 ? 8 :
5499 i == Xsand_stoneout_2 && j == 0 ? 10 :
5500 i == Xsand_stoneout_2 && j == 1 ? 12 :
5501 i == Xsand_stoneout_2 && j == 2 ? 14 :
5502 i == Xsand_stoneout_2 && j == 3 ? 16 :
5503 i == Xsand_stoneout_2 && j == 4 ? 18 :
5504 i == Xsand_stoneout_2 && j == 5 ? 22 :
5505 i == Xsand_stoneout_2 && j == 6 ? 26 :
5506 i == Xsand_stoneout_2 && j == 7 ? 30 :
5507 i == Xboom_bug && j == 2 ? 1 :
5508 i == Xboom_bug && j == 3 ? 2 :
5509 i == Xboom_bug && j == 4 ? 2 :
5510 i == Xboom_bug && j == 5 ? 1 :
5511 i == Xboom_bug && j == 6 ? 1 :
5512 i == Xboom_bug && j == 7 ? 0 :
5513 i == Xboom_bomb && j == 2 ? 1 :
5514 i == Xboom_bomb && j == 3 ? 2 :
5515 i == Xboom_bomb && j == 4 ? 2 :
5516 i == Xboom_bomb && j == 5 ? 1 :
5517 i == Xboom_bomb && j == 6 ? 1 :
5518 i == Xboom_bomb && j == 7 ? 0 :
5519 i == Xboom_android && j == 7 ? 3 :
5520 i == Xboom_1 && j == 2 ? 1 :
5521 i == Xboom_1 && j == 3 ? 2 :
5522 i == Xboom_1 && j == 4 ? 2 :
5523 i == Xboom_1 && j == 5 ? 3 :
5524 i == Xboom_1 && j == 6 ? 3 :
5525 i == Xboom_1 && j == 7 ? 4 :
5526 i == Xboom_2 && j == 0 ? 4 :
5527 i == Xboom_2 && j == 1 ? 4 :
5528 i == Xboom_2 && j == 2 ? 5 :
5529 i == Xboom_2 && j == 3 ? 5 :
5530 i == Xboom_2 && j == 4 ? 5 :
5531 i == Xboom_2 && j == 5 ? 6 :
5532 effective_action != action ? 0 :
5535 Bitmap *debug_bitmap = g_em->bitmap;
5536 int debug_src_x = g_em->src_x;
5537 int debug_src_y = g_em->src_y;
5540 int frame = getAnimationFrame(g->anim_frames,
5543 g->anim_start_frame,
5546 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y,
5547 g->double_movement && backside);
5550 g_em->bitmap = src_bitmap;
5551 g_em->src_x = src_x;
5552 g_em->src_y = src_y;
5553 g_em->src_offset_x = 0;
5554 g_em->src_offset_y = 0;
5555 g_em->dst_offset_x = 0;
5556 g_em->dst_offset_y = 0;
5557 g_em->width = TILEX;
5558 g_em->height = TILEY;
5562 if (!g->double_movement && (effective_action == ACTION_FALLING ||
5563 effective_action == ACTION_MOVING ||
5564 effective_action == ACTION_PUSHING))
5567 (effective_action == ACTION_FALLING ? MV_DOWN : direction);
5568 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? 1 : 0);
5569 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? 1 : 0);
5570 int cx = ABS(dx) * TILEX / 8;
5571 int cy = ABS(dy) * TILEY / 8;
5573 if (backside) /* tile where movement starts */
5575 if (dx < 0 || dy < 0)
5577 g_em->src_offset_x = cx * (j + 1);
5578 g_em->src_offset_y = cy * (j + 1);
5582 g_em->dst_offset_x = cx * (j + 1);
5583 g_em->dst_offset_y = cy * (j + 1);
5586 g_em->width = TILEX - cx * (j + 1);
5587 g_em->height = TILEY - cy * (j + 1);
5589 else /* tile where movement ends */
5591 if (dx < 0 || dy < 0)
5593 g_em->dst_offset_x = cx * (7 - j);
5594 g_em->dst_offset_y = cy * (7 - j);
5598 g_em->src_offset_x = cx * (7 - j);
5599 g_em->src_offset_y = cy * (7 - j);
5602 g_em->width = TILEX - cx * (7 - j);
5603 g_em->height = TILEY - cy * (7 - j);
5609 if (g_em->bitmap != debug_bitmap ||
5610 g_em->src_x != debug_src_x ||
5611 g_em->src_y != debug_src_y ||
5612 g_em->src_offset_x != 0 ||
5613 g_em->src_offset_y != 0 ||
5614 g_em->dst_offset_x != 0 ||
5615 g_em->dst_offset_y != 0 ||
5616 g_em->width != TILEX ||
5617 g_em->height != TILEY)
5619 static int last_i = -1;
5628 printf("::: EMC GFX ERROR for element %d -> %d ('%s')",
5629 i, element, element_info[element].token_name);
5631 if (element != effective_element)
5632 printf(" [%d ('%s')]",
5633 effective_element,element_info[effective_element].token_name);
5637 if (g_em->bitmap != debug_bitmap)
5638 printf(" %d(%d): different bitmap!\n",
5641 if (g_em->src_x != debug_src_x ||
5642 g_em->src_y != debug_src_y)
5643 printf(" frame %d (%c): %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
5644 j, (backside ? 'B' : 'F'),
5645 g_em->src_x, g_em->src_y,
5646 g_em->src_x / 32, g_em->src_y / 32,
5647 debug_src_x, debug_src_y,
5648 debug_src_x / 32, debug_src_y / 32);
5650 if (g_em->src_offset_x != 0 ||
5651 g_em->src_offset_y != 0 ||
5652 g_em->dst_offset_x != 0 ||
5653 g_em->dst_offset_y != 0)
5654 printf(" %d(%d): offsets %d,%d and %d,%d should be all 0\n",
5656 g_em->src_offset_x, g_em->src_offset_y,
5657 g_em->dst_offset_x, g_em->dst_offset_y);
5659 if (g_em->width != TILEX ||
5660 g_em->height != TILEY)
5661 printf(" %d(%d): size %d,%d should be %d,%d\n",
5663 g_em->width, g_em->height, TILEX, TILEY);