1 /***********************************************************
2 * Rocks'n'Diamonds -- McDuffin Strikes Back! *
3 *----------------------------------------------------------*
4 * (c) 1995-2002 Artsoft Entertainment *
6 * Detmolder Strasse 189 *
9 * e-mail: info@artsoft.org *
10 *----------------------------------------------------------*
12 ***********************************************************/
14 #include "libgame/libgame.h"
23 /* tool button identifiers */
24 #define TOOL_CTRL_ID_YES 0
25 #define TOOL_CTRL_ID_NO 1
26 #define TOOL_CTRL_ID_CONFIRM 2
27 #define TOOL_CTRL_ID_PLAYER_1 3
28 #define TOOL_CTRL_ID_PLAYER_2 4
29 #define TOOL_CTRL_ID_PLAYER_3 5
30 #define TOOL_CTRL_ID_PLAYER_4 6
32 #define NUM_TOOL_BUTTONS 7
34 /* forward declaration for internal use */
35 static void UnmapToolButtons();
36 static void HandleToolButtons(struct GadgetInfo *);
37 static int el_act_dir2crm(int, int, int);
38 static int el_act2crm(int, int);
40 static struct GadgetInfo *tool_gadget[NUM_TOOL_BUTTONS];
41 static int request_gadget_id = -1;
43 static char *print_if_not_empty(int element)
45 static char *s = NULL;
46 char *token_name = element_info[element].token_name;
51 s = checked_malloc(strlen(token_name) + 10 + 1);
53 if (element != EL_EMPTY)
54 sprintf(s, "%d\t['%s']", element, token_name);
56 sprintf(s, "%d", element);
61 void DumpTile(int x, int y)
67 printf("Field Info: SCREEN(%d, %d), LEVEL(%d, %d)\n", sx, sy, x, y);
70 if (!IN_LEV_FIELD(x, y))
72 printf("(not in level field)\n");
78 printf(" Feld: %d\t['%s']\n", Feld[x][y],
79 element_info[Feld[x][y]].token_name);
80 printf(" Back: %s\n", print_if_not_empty(Back[x][y]));
81 printf(" Store: %s\n", print_if_not_empty(Store[x][y]));
82 printf(" Store2: %s\n", print_if_not_empty(Store2[x][y]));
83 printf(" StorePlayer: %s\n", print_if_not_empty(StorePlayer[x][y]));
84 printf(" MovPos: %d\n", MovPos[x][y]);
85 printf(" MovDir: %d\n", MovDir[x][y]);
86 printf(" MovDelay: %d\n", MovDelay[x][y]);
87 printf(" ChangeDelay: %d\n", ChangeDelay[x][y]);
88 printf(" GfxElement: %d\n", GfxElement[x][y]);
89 printf(" GfxAction: %d\n", GfxAction[x][y]);
90 printf(" GfxFrame: %d\n", GfxFrame[x][y]);
94 void SetDrawtoField(int mode)
96 if (mode == DRAW_BUFFERED && setup.soft_scrolling)
107 drawto_field = fieldbuffer;
109 else /* DRAW_DIRECT, DRAW_BACKBUFFER */
115 BX2 = SCR_FIELDX - 1;
116 BY2 = SCR_FIELDY - 1;
120 drawto_field = (mode == DRAW_DIRECT ? window : backbuffer);
124 void RedrawPlayfield(boolean force_redraw, int x, int y, int width, int height)
126 if (game_status == GAME_MODE_PLAYING && !game.envelope_active)
132 width = gfx.sxsize + 2 * TILEX;
133 height = gfx.sysize + 2 * TILEY;
136 if (force_redraw || setup.direct_draw)
139 int x1 = (x - SX) / TILEX, y1 = (y - SY) / TILEY;
140 int x2 = (x - SX + width) / TILEX, y2 = (y - SY + height) / TILEY;
142 if (setup.direct_draw)
143 SetDrawtoField(DRAW_BACKBUFFER);
145 for (xx = BX1; xx <= BX2; xx++)
146 for (yy = BY1; yy <= BY2; yy++)
147 if (xx >= x1 && xx <= x2 && yy >= y1 && yy <= y2)
148 DrawScreenField(xx, yy);
151 if (setup.direct_draw)
152 SetDrawtoField(DRAW_DIRECT);
155 if (setup.soft_scrolling)
157 int fx = FX, fy = FY;
159 fx += (ScreenMovDir & (MV_LEFT|MV_RIGHT) ? ScreenGfxPos : 0);
160 fy += (ScreenMovDir & (MV_UP|MV_DOWN) ? ScreenGfxPos : 0);
162 BlitBitmap(fieldbuffer, backbuffer, fx,fy, SXSIZE,SYSIZE, SX,SY);
166 BlitBitmap(drawto, window, x, y, width, height, x, y);
172 DrawBuffer *buffer = (drawto_field == window ? backbuffer : drawto_field);
174 if (setup.direct_draw && game_status == GAME_MODE_PLAYING)
175 redraw_mask &= ~REDRAW_MAIN;
177 if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD)
178 redraw_mask |= REDRAW_FIELD;
180 if (redraw_mask & REDRAW_FIELD)
181 redraw_mask &= ~REDRAW_TILES;
183 if (redraw_mask == REDRAW_NONE)
186 if (global.fps_slowdown && game_status == GAME_MODE_PLAYING)
188 static boolean last_frame_skipped = FALSE;
189 boolean skip_even_when_not_scrolling = TRUE;
190 boolean just_scrolling = (ScreenMovDir != 0);
191 boolean verbose = FALSE;
193 if (global.fps_slowdown_factor > 1 &&
194 (FrameCounter % global.fps_slowdown_factor) &&
195 (just_scrolling || skip_even_when_not_scrolling))
197 redraw_mask &= ~REDRAW_MAIN;
199 last_frame_skipped = TRUE;
202 printf("FRAME SKIPPED\n");
206 if (last_frame_skipped)
207 redraw_mask |= REDRAW_FIELD;
209 last_frame_skipped = FALSE;
212 printf("frame not skipped\n");
216 /* synchronize X11 graphics at this point; if we would synchronize the
217 display immediately after the buffer switching (after the XFlush),
218 this could mean that we have to wait for the graphics to complete,
219 although we could go on doing calculations for the next frame */
223 if (redraw_mask & REDRAW_ALL)
225 BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
229 if (redraw_mask & REDRAW_FIELD)
231 if (game_status != GAME_MODE_PLAYING ||
232 redraw_mask & REDRAW_FROM_BACKBUFFER)
234 BlitBitmap(backbuffer, window,
235 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE, REAL_SX, REAL_SY);
239 int fx = FX, fy = FY;
241 if (setup.soft_scrolling)
243 fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
244 fy += (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
247 if (setup.soft_scrolling ||
248 ABS(ScreenMovPos) + ScrollStepSize == TILEX ||
249 ABS(ScreenMovPos) == ScrollStepSize ||
250 redraw_tiles > REDRAWTILES_THRESHOLD)
252 BlitBitmap(buffer, window, fx, fy, SXSIZE, SYSIZE, SX, SY);
256 printf("redrawing all (ScreenGfxPos == %d) because %s\n",
258 (setup.soft_scrolling ?
259 "setup.soft_scrolling" :
260 ABS(ScreenGfxPos) + ScrollStepSize == TILEX ?
261 "ABS(ScreenGfxPos) + ScrollStepSize == TILEX" :
262 ABS(ScreenGfxPos) == ScrollStepSize ?
263 "ABS(ScreenGfxPos) == ScrollStepSize" :
264 "redraw_tiles > REDRAWTILES_THRESHOLD"));
270 redraw_mask &= ~REDRAW_MAIN;
273 if (redraw_mask & REDRAW_DOORS)
275 if (redraw_mask & REDRAW_DOOR_1)
276 BlitBitmap(backbuffer, window, DX, DY, DXSIZE, DYSIZE, DX, DY);
278 if (redraw_mask & REDRAW_DOOR_2)
281 if ((redraw_mask & REDRAW_DOOR_2) == REDRAW_DOOR_2)
283 BlitBitmap(backbuffer, window, VX, VY, VXSIZE, VYSIZE, VX, VY);
287 if (redraw_mask & REDRAW_VIDEO_1)
288 BlitBitmap(backbuffer, window,
289 VX + VIDEO_DISPLAY1_XPOS, VY + VIDEO_DISPLAY1_YPOS,
290 VIDEO_DISPLAY_XSIZE, VIDEO_DISPLAY_YSIZE,
291 VX + VIDEO_DISPLAY1_XPOS, VY + VIDEO_DISPLAY1_YPOS);
292 if (redraw_mask & REDRAW_VIDEO_2)
293 BlitBitmap(backbuffer, window,
294 VX + VIDEO_DISPLAY2_XPOS, VY + VIDEO_DISPLAY2_YPOS,
295 VIDEO_DISPLAY_XSIZE, VIDEO_DISPLAY_YSIZE,
296 VX + VIDEO_DISPLAY2_XPOS, VY + VIDEO_DISPLAY2_YPOS);
297 if (redraw_mask & REDRAW_VIDEO_3)
298 BlitBitmap(backbuffer, window,
299 VX + VIDEO_CONTROL_XPOS, VY + VIDEO_CONTROL_YPOS,
300 VIDEO_CONTROL_XSIZE, VIDEO_CONTROL_YSIZE,
301 VX + VIDEO_CONTROL_XPOS, VY + VIDEO_CONTROL_YPOS);
306 if (redraw_mask & REDRAW_DOOR_3)
307 BlitBitmap(backbuffer, window, EX, EY, EXSIZE, EYSIZE, EX, EY);
309 redraw_mask &= ~REDRAW_DOORS;
312 if (redraw_mask & REDRAW_MICROLEVEL)
314 BlitBitmap(backbuffer, window, SX, SY + 10 * TILEY, SXSIZE, 7 * TILEY,
315 SX, SY + 10 * TILEY);
317 redraw_mask &= ~REDRAW_MICROLEVEL;
320 if (redraw_mask & REDRAW_TILES)
322 for (x = 0; x < SCR_FIELDX; x++)
323 for (y = 0 ; y < SCR_FIELDY; y++)
324 if (redraw[redraw_x1 + x][redraw_y1 + y])
325 BlitBitmap(buffer, window,
326 FX + x * TILEX, FY + y * TILEY, TILEX, TILEY,
327 SX + x * TILEX, SY + y * TILEY);
330 if (redraw_mask & REDRAW_FPS) /* display frames per second */
335 sprintf(info1, " (only every %d. frame)", global.fps_slowdown_factor);
336 if (!global.fps_slowdown)
339 sprintf(text, "%.1f fps%s", global.frames_per_second, info1);
340 DrawTextExt(window, SX, SY, text, FONT_TEXT_2, BLIT_OPAQUE);
345 for (x = 0; x < MAX_BUF_XSIZE; x++)
346 for (y = 0; y < MAX_BUF_YSIZE; y++)
349 redraw_mask = REDRAW_NONE;
355 long fading_delay = 300;
357 if (setup.fading && (redraw_mask & REDRAW_FIELD))
364 ClearRectangle(window, REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
367 for (i = 0; i < 2 * FULL_SYSIZE; i++)
369 for (y = 0; y < FULL_SYSIZE; y++)
371 BlitBitmap(backbuffer, window,
372 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
380 for (i = 1; i < FULL_SYSIZE; i+=2)
381 BlitBitmap(backbuffer, window,
382 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
388 SetClipOrigin(clip_gc[PIX_FADEMASK], 0, 0);
389 BlitBitmapMasked(backbuffer, window,
390 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
395 SetClipOrigin(clip_gc[PIX_FADEMASK], -1, -1);
396 BlitBitmapMasked(backbuffer, window,
397 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
402 SetClipOrigin(clip_gc[PIX_FADEMASK], 0, -1);
403 BlitBitmapMasked(backbuffer, window,
404 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
409 SetClipOrigin(clip_gc[PIX_FADEMASK], -1, 0);
410 BlitBitmapMasked(backbuffer, window,
411 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
416 redraw_mask &= ~REDRAW_MAIN;
423 void SetMainBackgroundImage(int graphic)
425 SetMainBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
426 graphic_info[graphic].bitmap ?
427 graphic_info[graphic].bitmap :
428 graphic_info[IMG_BACKGROUND].bitmap);
431 void SetDoorBackgroundImage(int graphic)
433 SetDoorBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
434 graphic_info[graphic].bitmap ?
435 graphic_info[graphic].bitmap :
436 graphic_info[IMG_BACKGROUND].bitmap);
439 void DrawBackground(int dst_x, int dst_y, int width, int height)
441 ClearRectangleOnBackground(backbuffer, dst_x, dst_y, width, height);
443 redraw_mask |= REDRAW_FIELD;
448 DrawBackground(REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
450 if (setup.soft_scrolling && game_status == GAME_MODE_PLAYING)
452 ClearRectangle(fieldbuffer, 0, 0, FXSIZE, FYSIZE);
453 SetDrawtoField(DRAW_BUFFERED);
456 SetDrawtoField(DRAW_BACKBUFFER);
458 if (setup.direct_draw && game_status == GAME_MODE_PLAYING)
460 ClearRectangle(window, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
461 SetDrawtoField(DRAW_DIRECT);
465 void MarkTileDirty(int x, int y)
467 int xx = redraw_x1 + x;
468 int yy = redraw_y1 + y;
473 redraw[xx][yy] = TRUE;
474 redraw_mask |= REDRAW_TILES;
477 void SetBorderElement()
481 BorderElement = EL_EMPTY;
483 for (y = 0; y < lev_fieldy && BorderElement == EL_EMPTY; y++)
485 for (x = 0; x < lev_fieldx; x++)
487 if (!IS_INDESTRUCTIBLE(Feld[x][y]))
488 BorderElement = EL_STEELWALL;
490 if (y != 0 && y != lev_fieldy - 1 && x != lev_fieldx - 1)
496 void SetRandomAnimationValue(int x, int y)
498 gfx.anim_random_frame = GfxRandom[x][y];
501 inline int getGraphicAnimationFrame(int graphic, int sync_frame)
503 /* animation synchronized with global frame counter, not move position */
504 if (graphic_info[graphic].anim_global_sync || sync_frame < 0)
505 sync_frame = FrameCounter;
507 return getAnimationFrame(graphic_info[graphic].anim_frames,
508 graphic_info[graphic].anim_delay,
509 graphic_info[graphic].anim_mode,
510 graphic_info[graphic].anim_start_frame,
514 inline void getGraphicSourceExt(int graphic, int frame, Bitmap **bitmap,
515 int *x, int *y, boolean get_backside)
517 struct GraphicInfo *g = &graphic_info[graphic];
518 int src_x = g->src_x + (get_backside ? g->offset2_x : 0);
519 int src_y = g->src_y + (get_backside ? g->offset2_y : 0);
523 if (g->offset_y == 0) /* frames are ordered horizontally */
525 int max_width = g->anim_frames_per_line * g->width;
527 int pos = (src_y / g->height) * max_width + src_x + frame * g->offset_x;
529 *x = pos % max_width;
530 *y = src_y % g->height + pos / max_width * g->height;
532 *x = (src_x + frame * g->offset_x) % max_width;
533 *y = src_y + (src_x + frame * g->offset_x) / max_width * g->height;
536 else if (g->offset_x == 0) /* frames are ordered vertically */
538 int max_height = g->anim_frames_per_line * g->height;
540 int pos = (src_x / g->width) * max_height + src_y + frame * g->offset_y;
542 *x = src_x % g->width + pos / max_height * g->width;
543 *y = pos % max_height;
545 *x = src_x + (src_y + frame * g->offset_y) / max_height * g->width;
546 *y = (src_y + frame * g->offset_y) % max_height;
549 else /* frames are ordered diagonally */
551 *x = src_x + frame * g->offset_x;
552 *y = src_y + frame * g->offset_y;
556 void getGraphicSource(int graphic, int frame, Bitmap **bitmap, int *x, int *y)
558 getGraphicSourceExt(graphic, frame, bitmap, x, y, FALSE);
561 void DrawGraphic(int x, int y, int graphic, int frame)
564 if (!IN_SCR_FIELD(x, y))
566 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
567 printf("DrawGraphic(): This should never happen!\n");
572 DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic, frame);
576 void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
582 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
583 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
586 void DrawGraphicThruMask(int x, int y, int graphic, int frame)
589 if (!IN_SCR_FIELD(x, y))
591 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
592 printf("DrawGraphicThruMask(): This should never happen!\n");
597 DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY, graphic,
602 void DrawGraphicThruMaskExt(DrawBuffer *d, int dst_x, int dst_y, int graphic,
608 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
610 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
611 dst_x - src_x, dst_y - src_y);
612 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dst_x, dst_y);
615 void DrawMiniGraphic(int x, int y, int graphic)
617 DrawMiniGraphicExt(drawto, SX + x * MINI_TILEX,SY + y * MINI_TILEY, graphic);
618 MarkTileDirty(x / 2, y / 2);
621 void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
623 struct GraphicInfo *g = &graphic_info[graphic];
625 int mini_starty = g->bitmap->height * 2 / 3;
628 *x = mini_startx + g->src_x / 2;
629 *y = mini_starty + g->src_y / 2;
632 void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
637 getMiniGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
638 BlitBitmap(src_bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
641 inline static void DrawGraphicShiftedNormal(int x, int y, int dx, int dy,
642 int graphic, int frame,
643 int cut_mode, int mask_mode)
648 int width = TILEX, height = TILEY;
651 if (dx || dy) /* shifted graphic */
653 if (x < BX1) /* object enters playfield from the left */
660 else if (x > BX2) /* object enters playfield from the right */
666 else if (x==BX1 && dx < 0) /* object leaves playfield to the left */
672 else if (x==BX2 && dx > 0) /* object leaves playfield to the right */
674 else if (dx) /* general horizontal movement */
675 MarkTileDirty(x + SIGN(dx), y);
677 if (y < BY1) /* object enters playfield from the top */
679 if (cut_mode==CUT_BELOW) /* object completely above top border */
687 else if (y > BY2) /* object enters playfield from the bottom */
693 else if (y==BY1 && dy < 0) /* object leaves playfield to the top */
699 else if (dy > 0 && cut_mode == CUT_ABOVE)
701 if (y == BY2) /* object completely above bottom border */
707 MarkTileDirty(x, y + 1);
708 } /* object leaves playfield to the bottom */
709 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
711 else if (dy) /* general vertical movement */
712 MarkTileDirty(x, y + SIGN(dy));
716 if (!IN_SCR_FIELD(x, y))
718 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
719 printf("DrawGraphicShifted(): This should never happen!\n");
724 if (width > 0 && height > 0)
726 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
731 dst_x = FX + x * TILEX + dx;
732 dst_y = FY + y * TILEY + dy;
734 if (mask_mode == USE_MASKING)
736 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
737 dst_x - src_x, dst_y - src_y);
738 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
742 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
749 inline static void DrawGraphicShiftedDouble(int x, int y, int dx, int dy,
750 int graphic, int frame,
751 int cut_mode, int mask_mode)
756 int width = TILEX, height = TILEY;
759 int x2 = x + SIGN(dx);
760 int y2 = y + SIGN(dy);
761 int anim_frames = graphic_info[graphic].anim_frames;
762 int sync_frame = (dx ? ABS(dx) : ABS(dy)) * anim_frames / TILESIZE;
764 /* re-calculate animation frame for two-tile movement animation */
765 frame = getGraphicAnimationFrame(graphic, sync_frame);
767 if (IN_SCR_FIELD(x1, y1)) /* movement start graphic inside screen area */
769 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, TRUE);
771 dst_x = FX + x1 * TILEX;
772 dst_y = FY + y1 * TILEY;
774 if (mask_mode == USE_MASKING)
776 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
777 dst_x - src_x, dst_y - src_y);
778 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
782 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
785 MarkTileDirty(x1, y1);
788 if (IN_SCR_FIELD(x2, y2)) /* movement end graphic inside screen area */
790 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, FALSE);
792 dst_x = FX + x2 * TILEX;
793 dst_y = FY + y2 * TILEY;
795 if (mask_mode == USE_MASKING)
797 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
798 dst_x - src_x, dst_y - src_y);
799 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
803 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
806 MarkTileDirty(x2, y2);
810 printf("::: DONE DrawGraphicShiftedDouble");
816 static void DrawGraphicShifted(int x, int y, int dx, int dy,
817 int graphic, int frame,
818 int cut_mode, int mask_mode)
822 DrawGraphic(x, y, graphic, frame);
827 if (graphic_info[graphic].double_movement) /* EM style movement images */
828 DrawGraphicShiftedDouble(x, y, dx, dy, graphic, frame, cut_mode,mask_mode);
830 DrawGraphicShiftedNormal(x, y, dx, dy, graphic, frame, cut_mode,mask_mode);
833 void DrawGraphicShiftedThruMask(int x, int y, int dx, int dy, int graphic,
834 int frame, int cut_mode)
836 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, USE_MASKING);
839 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
840 int cut_mode, int mask_mode)
842 int lx = LEVELX(x), ly = LEVELY(y);
846 if (IN_LEV_FIELD(lx, ly))
848 SetRandomAnimationValue(lx, ly);
850 graphic = el_act_dir2img(element, GfxAction[lx][ly], GfxDir[lx][ly]);
851 frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
853 /* do not use double (EM style) movement graphic when not moving */
854 if (graphic_info[graphic].double_movement && !dx && !dy)
856 graphic = el_act_dir2img(element, ACTION_DEFAULT, GfxDir[lx][ly]);
857 frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
860 else /* border element */
862 graphic = el2img(element);
863 frame = getGraphicAnimationFrame(graphic, -1);
866 if (element == EL_EXPANDABLE_WALL)
868 boolean left_stopped = FALSE, right_stopped = FALSE;
870 if (!IN_LEV_FIELD(lx - 1, ly) || IS_WALL(Feld[lx - 1][ly]))
872 if (!IN_LEV_FIELD(lx + 1, ly) || IS_WALL(Feld[lx + 1][ly]))
873 right_stopped = TRUE;
875 if (left_stopped && right_stopped)
877 else if (left_stopped)
879 graphic = IMG_EXPANDABLE_WALL_GROWING_RIGHT;
880 frame = graphic_info[graphic].anim_frames - 1;
882 else if (right_stopped)
884 graphic = IMG_EXPANDABLE_WALL_GROWING_LEFT;
885 frame = graphic_info[graphic].anim_frames - 1;
890 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
891 else if (mask_mode == USE_MASKING)
892 DrawGraphicThruMask(x, y, graphic, frame);
894 DrawGraphic(x, y, graphic, frame);
897 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
898 int cut_mode, int mask_mode)
900 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
901 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
902 cut_mode, mask_mode);
905 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
908 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
911 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
914 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
917 void DrawLevelElementThruMask(int x, int y, int element)
919 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
922 void DrawLevelFieldThruMask(int x, int y)
924 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
927 #define TILE_GFX_ELEMENT(x, y) \
928 (GfxElement[x][y] != EL_UNDEFINED && Feld[x][y] != EL_EXPLOSION ? \
929 GfxElement[x][y] : Feld[x][y])
931 static void DrawLevelFieldCrumbledSandExt(int x, int y, int graphic, int frame)
935 int sx = SCREENX(x), sy = SCREENY(y);
937 int width, height, cx, cy, i;
939 int crumbled_border_size = graphic_info[graphic].border_size;
941 int snip = TILEX / 8; /* number of border pixels from "crumbled graphic" */
943 static int xy[4][2] =
952 if (x == 0 && y == 7)
953 printf("::: %d, %d [%d]\n", GfxElement[x][y], Feld[x][y],
954 crumbled_border_size);
957 if (!IN_LEV_FIELD(x, y))
960 element = TILE_GFX_ELEMENT(x, y);
962 /* crumble field itself */
963 if (GFX_CRUMBLED(element) && !IS_MOVING(x, y))
965 if (!IN_SCR_FIELD(sx, sy))
968 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
970 for (i = 0; i < 4; i++)
972 int xx = x + xy[i][0];
973 int yy = y + xy[i][1];
976 element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
979 element = (IN_LEV_FIELD(xx, yy) ? Feld[xx][yy] : BorderElement);
982 /* check if neighbour field is of same type */
983 if (GFX_CRUMBLED(element) && !IS_MOVING(xx, yy))
987 if (Feld[x][y] == EL_CUSTOM_START + 123)
988 printf("::: crumble [%d] THE CHAOS ENGINE (%d, %d): %d, %d\n",
989 i, Feld[x][y], element,
990 GFX_CRUMBLED(element), IS_MOVING(x, y));
993 if (i == 1 || i == 2)
995 width = crumbled_border_size;
997 cx = (i == 2 ? TILEX - crumbled_border_size : 0);
1003 height = crumbled_border_size;
1005 cy = (i == 3 ? TILEY - crumbled_border_size : 0);
1008 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1009 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
1012 MarkTileDirty(sx, sy);
1014 else /* crumble neighbour fields */
1017 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1020 for (i = 0; i < 4; i++)
1022 int xx = x + xy[i][0];
1023 int yy = y + xy[i][1];
1024 int sxx = sx + xy[i][0];
1025 int syy = sy + xy[i][1];
1028 if (!IN_LEV_FIELD(xx, yy) ||
1029 !IN_SCR_FIELD(sxx, syy) ||
1033 element = TILE_GFX_ELEMENT(xx, yy);
1035 if (!GFX_CRUMBLED(element))
1038 if (!IN_LEV_FIELD(xx, yy) ||
1039 !IN_SCR_FIELD(sxx, syy) ||
1040 !GFX_CRUMBLED(Feld[xx][yy]) ||
1046 graphic = el_act2crm(Feld[xx][yy], ACTION_DEFAULT);
1047 crumbled_border_size = graphic_info[graphic].border_size;
1049 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1052 if (i == 1 || i == 2)
1054 width = crumbled_border_size;
1056 cx = (i == 1 ? TILEX - crumbled_border_size : 0);
1062 height = crumbled_border_size;
1064 cy = (i == 0 ? TILEY - crumbled_border_size : 0);
1067 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1068 width, height, FX + sxx * TILEX + cx, FY + syy * TILEY + cy);
1070 MarkTileDirty(sxx, syy);
1075 void DrawLevelFieldCrumbledSand(int x, int y)
1080 if (!IN_LEV_FIELD(x, y))
1083 graphic = el_act2crm(Feld[x][y], ACTION_DEFAULT);
1085 DrawLevelFieldCrumbledSandExt(x, y, graphic, 0);
1087 DrawLevelFieldCrumbledSandExt(x, y, IMG_SAND_CRUMBLED, 0);
1091 void DrawLevelFieldCrumbledSandDigging(int x, int y, int direction,
1095 int graphic1 = el_act_dir2img(GfxElement[x][y], ACTION_DIGGING, direction);
1096 int graphic2 = el_act_dir2crm(GfxElement[x][y], ACTION_DIGGING, direction);
1098 int graphic1 = el_act_dir2img(EL_SAND, ACTION_DIGGING, direction);
1099 int graphic2 = el_act_dir2img(EL_SAND_CRUMBLED, ACTION_DIGGING, direction);
1101 int frame1 = getGraphicAnimationFrame(graphic1, step_frame);
1102 int frame2 = getGraphicAnimationFrame(graphic2, step_frame);
1103 int sx = SCREENX(x), sy = SCREENY(y);
1105 DrawGraphic(sx, sy, graphic1, frame1);
1106 DrawLevelFieldCrumbledSandExt(x, y, graphic2, frame2);
1109 void DrawLevelFieldCrumbledSandNeighbours(int x, int y)
1111 int sx = SCREENX(x), sy = SCREENY(y);
1112 static int xy[4][2] =
1121 for (i = 0; i < 4; i++)
1123 int xx = x + xy[i][0];
1124 int yy = y + xy[i][1];
1125 int sxx = sx + xy[i][0];
1126 int syy = sy + xy[i][1];
1128 if (!IN_LEV_FIELD(xx, yy) ||
1129 !IN_SCR_FIELD(sxx, syy) ||
1130 !GFX_CRUMBLED(Feld[xx][yy]) ||
1134 DrawLevelField(xx, yy);
1138 static int getBorderElement(int x, int y)
1142 { EL_STEELWALL_TOPLEFT, EL_INVISIBLE_STEELWALL_TOPLEFT },
1143 { EL_STEELWALL_TOPRIGHT, EL_INVISIBLE_STEELWALL_TOPRIGHT },
1144 { EL_STEELWALL_BOTTOMLEFT, EL_INVISIBLE_STEELWALL_BOTTOMLEFT },
1145 { EL_STEELWALL_BOTTOMRIGHT, EL_INVISIBLE_STEELWALL_BOTTOMRIGHT },
1146 { EL_STEELWALL_VERTICAL, EL_INVISIBLE_STEELWALL_VERTICAL },
1147 { EL_STEELWALL_HORIZONTAL, EL_INVISIBLE_STEELWALL_HORIZONTAL },
1148 { EL_STEELWALL, EL_INVISIBLE_STEELWALL }
1150 int steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
1151 int steel_position = (x == -1 && y == -1 ? 0 :
1152 x == lev_fieldx && y == -1 ? 1 :
1153 x == -1 && y == lev_fieldy ? 2 :
1154 x == lev_fieldx && y == lev_fieldy ? 3 :
1155 x == -1 || x == lev_fieldx ? 4 :
1156 y == -1 || y == lev_fieldy ? 5 : 6);
1158 return border[steel_position][steel_type];
1161 void DrawScreenElement(int x, int y, int element)
1163 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1164 DrawLevelFieldCrumbledSand(LEVELX(x), LEVELY(y));
1167 void DrawLevelElement(int x, int y, int element)
1169 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1170 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1173 void DrawScreenField(int x, int y)
1175 int lx = LEVELX(x), ly = LEVELY(y);
1176 int element, content;
1178 if (!IN_LEV_FIELD(lx, ly))
1180 if (lx < -1 || lx > lev_fieldx || ly < -1 || ly > lev_fieldy)
1183 element = getBorderElement(lx, ly);
1185 DrawScreenElement(x, y, element);
1189 element = Feld[lx][ly];
1190 content = Store[lx][ly];
1192 if (IS_MOVING(lx, ly))
1194 int horiz_move = (MovDir[lx][ly] == MV_LEFT || MovDir[lx][ly] == MV_RIGHT);
1195 boolean cut_mode = NO_CUTTING;
1197 if (element == EL_QUICKSAND_EMPTYING ||
1198 element == EL_MAGIC_WALL_EMPTYING ||
1199 element == EL_BD_MAGIC_WALL_EMPTYING ||
1200 element == EL_AMOEBA_DROPPING)
1201 cut_mode = CUT_ABOVE;
1202 else if (element == EL_QUICKSAND_FILLING ||
1203 element == EL_MAGIC_WALL_FILLING ||
1204 element == EL_BD_MAGIC_WALL_FILLING)
1205 cut_mode = CUT_BELOW;
1207 if (cut_mode == CUT_ABOVE)
1208 DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1210 DrawScreenElement(x, y, EL_EMPTY);
1213 DrawScreenElementShifted(x, y, MovPos[lx][ly], 0, element, NO_CUTTING);
1214 else if (cut_mode == NO_CUTTING)
1215 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], element, cut_mode);
1217 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], content, cut_mode);
1219 if (content == EL_ACID)
1221 int dir = MovDir[lx][ly];
1222 int newlx = lx + (dir == MV_LEFT ? -1 : dir == MV_RIGHT ? +1 : 0);
1223 int newly = ly + (dir == MV_UP ? -1 : dir == MV_DOWN ? +1 : 0);
1225 DrawLevelElementThruMask(newlx, newly, EL_ACID);
1228 else if (IS_BLOCKED(lx, ly))
1233 boolean cut_mode = NO_CUTTING;
1234 int element_old, content_old;
1236 Blocked2Moving(lx, ly, &oldx, &oldy);
1239 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1240 MovDir[oldx][oldy] == MV_RIGHT);
1242 element_old = Feld[oldx][oldy];
1243 content_old = Store[oldx][oldy];
1245 if (element_old == EL_QUICKSAND_EMPTYING ||
1246 element_old == EL_MAGIC_WALL_EMPTYING ||
1247 element_old == EL_BD_MAGIC_WALL_EMPTYING ||
1248 element_old == EL_AMOEBA_DROPPING)
1249 cut_mode = CUT_ABOVE;
1251 DrawScreenElement(x, y, EL_EMPTY);
1254 DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
1256 else if (cut_mode == NO_CUTTING)
1257 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
1260 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
1263 else if (IS_DRAWABLE(element))
1264 DrawScreenElement(x, y, element);
1266 DrawScreenElement(x, y, EL_EMPTY);
1269 void DrawLevelField(int x, int y)
1271 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1272 DrawScreenField(SCREENX(x), SCREENY(y));
1273 else if (IS_MOVING(x, y))
1277 Moving2Blocked(x, y, &newx, &newy);
1278 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1279 DrawScreenField(SCREENX(newx), SCREENY(newy));
1281 else if (IS_BLOCKED(x, y))
1285 Blocked2Moving(x, y, &oldx, &oldy);
1286 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1287 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1291 void DrawMiniElement(int x, int y, int element)
1295 graphic = el2edimg(element);
1296 DrawMiniGraphic(x, y, graphic);
1299 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1301 int x = sx + scroll_x, y = sy + scroll_y;
1303 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1304 DrawMiniElement(sx, sy, EL_EMPTY);
1305 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1306 DrawMiniElement(sx, sy, Feld[x][y]);
1308 DrawMiniGraphic(sx, sy, el2edimg(getBorderElement(x, y)));
1311 void DrawEnvelopeBackground(int envelope_nr, int startx, int starty,
1312 int x, int y, int xsize, int ysize, int font_nr)
1314 int font_width = getFontWidth(font_nr);
1315 int font_height = getFontHeight(font_nr);
1316 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1319 int dst_x = SX + startx + x * font_width;
1320 int dst_y = SY + starty + y * font_height;
1321 int width = graphic_info[graphic].width;
1322 int height = graphic_info[graphic].height;
1323 int inner_width = MAX(width - 2 * font_width, font_width);
1324 int inner_height = MAX(height - 2 * font_height, font_height);
1325 int inner_sx = (width >= 3 * font_width ? font_width : 0);
1326 int inner_sy = (height >= 3 * font_height ? font_height : 0);
1327 boolean draw_masked = graphic_info[graphic].draw_masked;
1329 getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
1331 if (src_bitmap == NULL || width < font_width || height < font_height)
1333 ClearRectangle(drawto, dst_x, dst_y, font_width, font_height);
1337 src_x += (x == 0 ? 0 : x == xsize - 1 ? width - font_width :
1338 inner_sx + (x - 1) * font_width % inner_width);
1339 src_y += (y == 0 ? 0 : y == ysize - 1 ? height - font_height :
1340 inner_sy + (y - 1) * font_height % inner_height);
1344 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1345 dst_x - src_x, dst_y - src_y);
1346 BlitBitmapMasked(src_bitmap, drawto, src_x, src_y, font_width, font_height,
1350 BlitBitmap(src_bitmap, drawto, src_x, src_y, font_width, font_height,
1354 void AnimateEnvelope(int envelope_nr, int anim_mode, int action)
1356 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1358 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
1359 int mask_mode = (src_bitmap != NULL ? BLIT_MASKED : BLIT_ON_BACKGROUND);
1361 boolean draw_masked = graphic_info[graphic].draw_masked;
1362 int mask_mode = (draw_masked ? BLIT_MASKED : BLIT_ON_BACKGROUND);
1364 boolean ffwd_delay = (tape.playing && tape.fast_forward);
1365 boolean no_delay = (tape.warp_forward);
1366 unsigned long anim_delay = 0;
1367 int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
1368 int anim_delay_value = (no_delay ? 0 : frame_delay_value);
1369 int font_nr = FONT_ENVELOPE_1 + envelope_nr;
1370 int font_width = getFontWidth(font_nr);
1371 int font_height = getFontHeight(font_nr);
1372 int max_xsize = level.envelope_xsize[envelope_nr];
1373 int max_ysize = level.envelope_ysize[envelope_nr];
1374 int xstart = (anim_mode & ANIM_VERTICAL ? max_xsize : 0);
1375 int ystart = (anim_mode & ANIM_HORIZONTAL ? max_ysize : 0);
1376 int xend = max_xsize;
1377 int yend = (anim_mode != ANIM_DEFAULT ? max_ysize : 0);
1378 int xstep = (xstart < xend ? 1 : 0);
1379 int ystep = (ystart < yend || xstep == 0 ? 1 : 0);
1382 for (x = xstart, y = ystart; x <= xend && y <= yend; x += xstep, y += ystep)
1384 int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2;
1385 int ysize = (action == ACTION_CLOSING ? yend - (y - ystart) : y) + 2;
1386 int sx = (SXSIZE - xsize * font_width) / 2;
1387 int sy = (SYSIZE - ysize * font_height) / 2;
1390 SetDrawtoField(DRAW_BUFFERED);
1392 BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
1394 SetDrawtoField(DRAW_BACKBUFFER);
1396 for (yy = 0; yy < ysize; yy++) for (xx = 0; xx < xsize; xx++)
1397 DrawEnvelopeBackground(envelope_nr, sx,sy, xx,yy, xsize, ysize, font_nr);
1399 DrawTextToTextArea(SX + sx + font_width, SY + sy + font_height,
1400 level.envelope_text[envelope_nr], font_nr, max_xsize,
1401 xsize - 2, ysize - 2, mask_mode);
1403 redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
1406 WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
1410 void ShowEnvelope(int envelope_nr)
1412 int element = EL_ENVELOPE_1 + envelope_nr;
1413 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1414 int sound_opening = element_info[element].sound[ACTION_OPENING];
1415 int sound_closing = element_info[element].sound[ACTION_CLOSING];
1416 boolean ffwd_delay = (tape.playing && tape.fast_forward);
1417 boolean no_delay = (tape.warp_forward);
1418 int normal_delay_value = ONE_SECOND_DELAY / (ffwd_delay ? 2 : 1);
1419 int wait_delay_value = (no_delay ? 0 : normal_delay_value);
1420 int anim_mode = graphic_info[graphic].anim_mode;
1421 int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL:
1422 anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode);
1424 game.envelope_active = TRUE; /* needed for RedrawPlayfield() events */
1426 PlaySoundStereo(sound_opening, SOUND_MIDDLE);
1428 if (anim_mode == ANIM_DEFAULT)
1429 AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_OPENING);
1431 AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_OPENING);
1434 Delay(wait_delay_value);
1436 WaitForEventToContinue();
1438 PlaySoundStereo(sound_closing, SOUND_MIDDLE);
1440 if (anim_mode != ANIM_NONE)
1441 AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_CLOSING);
1443 if (anim_mode == ANIM_DEFAULT)
1444 AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_CLOSING);
1446 game.envelope_active = FALSE;
1448 SetDrawtoField(DRAW_BUFFERED);
1450 redraw_mask |= REDRAW_FIELD;
1454 void getMicroGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1456 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
1457 int mini_startx = src_bitmap->width * 3 / 4;
1458 int mini_starty = src_bitmap->height * 2 / 3;
1459 int src_x = mini_startx + graphic_info[graphic].src_x / 8;
1460 int src_y = mini_starty + graphic_info[graphic].src_y / 8;
1462 *bitmap = src_bitmap;
1467 void DrawMicroElement(int xpos, int ypos, int element)
1471 int graphic = el2preimg(element);
1473 getMicroGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1474 BlitBitmap(src_bitmap, drawto, src_x, src_y, MICRO_TILEX, MICRO_TILEY,
1482 SetDrawBackgroundMask(REDRAW_NONE);
1485 for (x = BX1; x <= BX2; x++)
1486 for (y = BY1; y <= BY2; y++)
1487 DrawScreenField(x, y);
1489 redraw_mask |= REDRAW_FIELD;
1492 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1496 for (x = 0; x < size_x; x++)
1497 for (y = 0; y < size_y; y++)
1498 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1500 redraw_mask |= REDRAW_FIELD;
1503 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1507 DrawBackground(xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
1509 if (lev_fieldx < STD_LEV_FIELDX)
1510 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1511 if (lev_fieldy < STD_LEV_FIELDY)
1512 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1514 xpos += MICRO_TILEX;
1515 ypos += MICRO_TILEY;
1517 for (x = -1; x <= STD_LEV_FIELDX; x++)
1519 for (y = -1; y <= STD_LEV_FIELDY; y++)
1521 int lx = from_x + x, ly = from_y + y;
1523 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1524 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1525 level.field[lx][ly]);
1526 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1
1527 && BorderElement != EL_EMPTY)
1528 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1529 getBorderElement(lx, ly));
1533 redraw_mask |= REDRAW_MICROLEVEL;
1536 #define MICROLABEL_EMPTY 0
1537 #define MICROLABEL_LEVEL_NAME 1
1538 #define MICROLABEL_CREATED_BY 2
1539 #define MICROLABEL_LEVEL_AUTHOR 3
1540 #define MICROLABEL_IMPORTED_FROM 4
1541 #define MICROLABEL_LEVEL_IMPORT_INFO 5
1543 static void DrawMicroLevelLabelExt(int mode)
1545 char label_text[MAX_OUTPUT_LINESIZE + 1];
1546 int max_len_label_text;
1547 int font_nr = FONT_TEXT_2;
1549 if (mode == MICROLABEL_CREATED_BY || mode == MICROLABEL_IMPORTED_FROM)
1550 font_nr = FONT_TEXT_3;
1552 max_len_label_text = SXSIZE / getFontWidth(font_nr);
1554 DrawBackground(SX, MICROLABEL_YPOS, SXSIZE, getFontHeight(font_nr));
1556 strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
1557 mode == MICROLABEL_CREATED_BY ? "created by" :
1558 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
1559 mode == MICROLABEL_IMPORTED_FROM ? "imported from" :
1560 mode == MICROLABEL_LEVEL_IMPORT_INFO ?
1561 leveldir_current->imported_from : ""),
1562 max_len_label_text);
1563 label_text[max_len_label_text] = '\0';
1565 if (strlen(label_text) > 0)
1567 int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
1568 int lypos = MICROLABEL_YPOS;
1570 DrawText(lxpos, lypos, label_text, font_nr);
1573 redraw_mask |= REDRAW_MICROLEVEL;
1576 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1578 static unsigned long scroll_delay = 0;
1579 static unsigned long label_delay = 0;
1580 static int from_x, from_y, scroll_direction;
1581 static int label_state, label_counter;
1582 int last_game_status = game_status; /* save current game status */
1584 /* force PREVIEW font on preview level */
1585 game_status = GAME_MODE_PSEUDO_PREVIEW;
1589 from_x = from_y = 0;
1590 scroll_direction = MV_RIGHT;
1594 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1595 DrawMicroLevelLabelExt(label_state);
1597 /* initialize delay counters */
1598 DelayReached(&scroll_delay, 0);
1599 DelayReached(&label_delay, 0);
1601 if (leveldir_current->name)
1603 int text_width = getTextWidth(leveldir_current->name, FONT_TEXT_1);
1604 int lxpos = SX + (SXSIZE - text_width) / 2;
1605 int lypos = SY + 352;
1607 DrawText(lxpos, lypos, leveldir_current->name, FONT_TEXT_1);
1610 game_status = last_game_status; /* restore current game status */
1615 /* scroll micro level, if needed */
1616 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1617 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1619 switch (scroll_direction)
1625 scroll_direction = MV_UP;
1629 if (from_x < lev_fieldx - STD_LEV_FIELDX)
1632 scroll_direction = MV_DOWN;
1639 scroll_direction = MV_RIGHT;
1643 if (from_y < lev_fieldy - STD_LEV_FIELDY)
1646 scroll_direction = MV_LEFT;
1653 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1656 /* redraw micro level label, if needed */
1657 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1658 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1659 strcmp(level.author, leveldir_current->name) != 0 &&
1660 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1662 int max_label_counter = 23;
1664 if (leveldir_current->imported_from != NULL)
1665 max_label_counter += 14;
1667 label_counter = (label_counter + 1) % max_label_counter;
1668 label_state = (label_counter >= 0 && label_counter <= 7 ?
1669 MICROLABEL_LEVEL_NAME :
1670 label_counter >= 9 && label_counter <= 12 ?
1671 MICROLABEL_CREATED_BY :
1672 label_counter >= 14 && label_counter <= 21 ?
1673 MICROLABEL_LEVEL_AUTHOR :
1674 label_counter >= 23 && label_counter <= 26 ?
1675 MICROLABEL_IMPORTED_FROM :
1676 label_counter >= 28 && label_counter <= 35 ?
1677 MICROLABEL_LEVEL_IMPORT_INFO : MICROLABEL_EMPTY);
1678 DrawMicroLevelLabelExt(label_state);
1681 game_status = last_game_status; /* restore current game status */
1684 inline void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
1685 int graphic, int sync_frame, int mask_mode)
1687 int frame = getGraphicAnimationFrame(graphic, sync_frame);
1689 if (mask_mode == USE_MASKING)
1690 DrawGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
1692 DrawGraphicExt(dst_bitmap, x, y, graphic, frame);
1695 inline void DrawGraphicAnimation(int x, int y, int graphic)
1697 int lx = LEVELX(x), ly = LEVELY(y);
1699 if (!IN_SCR_FIELD(x, y))
1702 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
1703 graphic, GfxFrame[lx][ly], NO_MASKING);
1704 MarkTileDirty(x, y);
1707 void DrawLevelGraphicAnimation(int x, int y, int graphic)
1709 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
1712 void DrawLevelElementAnimation(int x, int y, int element)
1715 int graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
1717 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
1719 DrawGraphicAnimation(SCREENX(x), SCREENY(y), el2img(element));
1723 inline void DrawLevelGraphicAnimationIfNeeded(int x, int y, int graphic)
1725 int sx = SCREENX(x), sy = SCREENY(y);
1727 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
1730 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
1733 DrawGraphicAnimation(sx, sy, graphic);
1735 if (GFX_CRUMBLED(Feld[x][y]))
1736 DrawLevelFieldCrumbledSand(x, y);
1739 void DrawLevelElementAnimationIfNeeded(int x, int y, int element)
1741 int sx = SCREENX(x), sy = SCREENY(y);
1744 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
1747 graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
1749 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
1752 DrawGraphicAnimation(sx, sy, graphic);
1754 if (GFX_CRUMBLED(element))
1755 DrawLevelFieldCrumbledSand(x, y);
1758 static int getPlayerGraphic(struct PlayerInfo *player, int move_dir)
1760 if (player->use_murphy_graphic)
1762 /* this works only because currently only one player can be "murphy" ... */
1763 static int last_horizontal_dir = MV_LEFT;
1764 int graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, move_dir);
1766 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
1767 last_horizontal_dir = move_dir;
1769 if (graphic == IMG_SP_MURPHY) /* undefined => use special graphic */
1771 int direction = (player->is_snapping ? move_dir : last_horizontal_dir);
1773 graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, direction);
1779 return el_act_dir2img(player->element_nr, player->GfxAction, move_dir);
1782 static boolean equalGraphics(int graphic1, int graphic2)
1784 struct GraphicInfo *g1 = &graphic_info[graphic1];
1785 struct GraphicInfo *g2 = &graphic_info[graphic2];
1787 return (g1->bitmap == g2->bitmap &&
1788 g1->src_x == g2->src_x &&
1789 g1->src_y == g2->src_y &&
1790 g1->anim_frames == g2->anim_frames &&
1791 g1->anim_delay == g2->anim_delay &&
1792 g1->anim_mode == g2->anim_mode);
1795 void DrawAllPlayers()
1799 for (i = 0; i < MAX_PLAYERS; i++)
1800 if (stored_player[i].active)
1801 DrawPlayer(&stored_player[i]);
1804 void DrawPlayerField(int x, int y)
1806 if (!IS_PLAYER(x, y))
1809 DrawPlayer(PLAYERINFO(x, y));
1812 void DrawPlayer(struct PlayerInfo *player)
1814 int jx = player->jx;
1815 int jy = player->jy;
1816 int move_dir = player->MovDir;
1818 int last_jx = player->last_jx;
1819 int last_jy = player->last_jy;
1820 int next_jx = jx + (jx - last_jx);
1821 int next_jy = jy + (jy - last_jy);
1822 boolean player_is_moving = (last_jx != jx || last_jy != jy ? TRUE : FALSE);
1824 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? +1 : 0);
1825 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? +1 : 0);
1826 int last_jx = (player->is_moving ? jx - dx : jx);
1827 int last_jy = (player->is_moving ? jy - dy : jy);
1828 int next_jx = jx + dx;
1829 int next_jy = jy + dy;
1830 boolean player_is_moving = (player->MovPos ? TRUE : FALSE);
1832 int sx = SCREENX(jx), sy = SCREENY(jy);
1833 int sxx = 0, syy = 0;
1834 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
1836 int action = ACTION_DEFAULT;
1837 int last_player_graphic = getPlayerGraphic(player, move_dir);
1838 int last_player_frame = player->Frame;
1841 if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
1845 if (!IN_LEV_FIELD(jx, jy))
1847 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
1848 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
1849 printf("DrawPlayerField(): This should never happen!\n");
1854 if (element == EL_EXPLOSION)
1857 action = (player->is_pushing ? ACTION_PUSHING :
1858 player->is_digging ? ACTION_DIGGING :
1859 player->is_collecting ? ACTION_COLLECTING :
1860 player->is_moving ? ACTION_MOVING :
1861 player->is_snapping ? ACTION_SNAPPING :
1862 player->is_dropping ? ACTION_DROPPING :
1863 player->is_waiting ? player->action_waiting : ACTION_DEFAULT);
1865 InitPlayerGfxAnimation(player, action, move_dir);
1867 /* ----------------------------------------------------------------------- */
1868 /* draw things in the field the player is leaving, if needed */
1869 /* ----------------------------------------------------------------------- */
1872 if (player->is_moving)
1874 if (player_is_moving)
1877 if (Back[last_jx][last_jy] && IS_DRAWABLE(last_element))
1879 DrawLevelElement(last_jx, last_jy, Back[last_jx][last_jy]);
1881 if (last_element == EL_DYNAMITE_ACTIVE ||
1882 last_element == EL_SP_DISK_RED_ACTIVE)
1883 DrawDynamite(last_jx, last_jy);
1885 DrawLevelFieldThruMask(last_jx, last_jy);
1887 else if (last_element == EL_DYNAMITE_ACTIVE ||
1888 last_element == EL_SP_DISK_RED_ACTIVE)
1889 DrawDynamite(last_jx, last_jy);
1891 DrawLevelField(last_jx, last_jy);
1893 if (player->is_pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
1894 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
1897 if (!IN_SCR_FIELD(sx, sy))
1900 if (setup.direct_draw)
1901 SetDrawtoField(DRAW_BUFFERED);
1903 /* ----------------------------------------------------------------------- */
1904 /* draw things behind the player, if needed */
1905 /* ----------------------------------------------------------------------- */
1908 DrawLevelElement(jx, jy, Back[jx][jy]);
1909 else if (IS_ACTIVE_BOMB(element))
1910 DrawLevelElement(jx, jy, EL_EMPTY);
1913 if (player_is_moving && GfxElement[jx][jy] != EL_UNDEFINED)
1915 if (GFX_CRUMBLED(GfxElement[jx][jy]))
1916 DrawLevelFieldCrumbledSandDigging(jx, jy, move_dir, player->StepFrame);
1919 int old_element = GfxElement[jx][jy];
1920 int old_graphic = el_act_dir2img(old_element, action, move_dir);
1921 int frame = getGraphicAnimationFrame(old_graphic, player->StepFrame);
1923 DrawGraphic(sx, sy, old_graphic, frame);
1928 GfxElement[jx][jy] = EL_UNDEFINED;
1930 DrawLevelField(jx, jy);
1934 /* ----------------------------------------------------------------------- */
1935 /* draw player himself */
1936 /* ----------------------------------------------------------------------- */
1940 graphic = getPlayerGraphic(player, move_dir);
1942 /* in the case of changed player action or direction, prevent the current
1943 animation frame from being restarted for identical animations */
1944 if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic))
1945 player->Frame = last_player_frame;
1949 if (player->use_murphy_graphic)
1951 static int last_horizontal_dir = MV_LEFT;
1953 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
1954 last_horizontal_dir = move_dir;
1956 graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, move_dir);
1958 if (graphic == IMG_SP_MURPHY) /* undefined => use special graphic */
1960 int direction = (player->is_snapping ? move_dir : last_horizontal_dir);
1962 graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, direction);
1966 graphic = el_act_dir2img(player->element_nr, player->GfxAction, move_dir);
1970 frame = getGraphicAnimationFrame(graphic, player->Frame);
1974 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
1975 sxx = player->GfxPos;
1977 syy = player->GfxPos;
1980 if (!setup.soft_scrolling && ScreenMovPos)
1983 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
1985 if (SHIELD_ON(player))
1987 int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
1988 IMG_SHIELD_NORMAL_ACTIVE);
1989 int frame = getGraphicAnimationFrame(graphic, -1);
1991 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
1994 /* ----------------------------------------------------------------------- */
1995 /* draw things the player is pushing, if needed */
1996 /* ----------------------------------------------------------------------- */
1999 printf("::: %d, %d [%d, %d] [%d]\n",
2000 player->is_pushing, player_is_moving, player->GfxAction,
2001 player->is_moving, player_is_moving);
2005 if (player->is_pushing && player->is_moving)
2007 if (player->is_pushing && player_is_moving)
2011 int px = SCREENX(jx), py = SCREENY(jy);
2012 int pxx = (TILEX - ABS(sxx)) * dx;
2013 int pyy = (TILEY - ABS(syy)) * dy;
2015 int px = SCREENX(next_jx), py = SCREENY(next_jy);
2024 if (!IS_MOVING(jx, jy)) /* push movement already finished */
2025 element = Feld[next_jx][next_jy];
2027 graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
2028 frame = getGraphicAnimationFrame(graphic, player->StepFrame);
2030 /* draw background element under pushed element (like the Sokoban field) */
2031 if (Back[next_jx][next_jy])
2032 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
2034 /* masked drawing is needed for EMC style (double) movement graphics */
2035 DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame, NO_CUTTING);
2038 if (Back[next_jx][next_jy])
2039 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
2041 if ((pxx || pyy) && element == EL_SOKOBAN_OBJECT)
2042 DrawGraphicShiftedThruMask(px, py, pxx, pyy, IMG_SOKOBAN_OBJECT, 0,
2046 int element = MovingOrBlocked2Element(next_jx, next_jy);
2047 int graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
2049 int frame = getGraphicAnimationFrame(graphic, player->StepFrame);
2051 int frame = getGraphicAnimationFrame(graphic, player->Frame);
2055 /* masked drawing is needed for EMC style (double) movement graphics */
2056 DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame,
2059 DrawGraphicShifted(px, py, pxx, pyy, graphic, frame,
2060 NO_CUTTING, NO_MASKING);
2066 /* ----------------------------------------------------------------------- */
2067 /* draw things in front of player (active dynamite or dynabombs) */
2068 /* ----------------------------------------------------------------------- */
2070 if (IS_ACTIVE_BOMB(element))
2072 graphic = el2img(element);
2073 frame = getGraphicAnimationFrame(graphic, GfxFrame[jx][jy]);
2075 if (game.emulation == EMU_SUPAPLEX)
2076 DrawGraphic(sx, sy, IMG_SP_DISK_RED, frame);
2078 DrawGraphicThruMask(sx, sy, graphic, frame);
2081 if (player_is_moving && last_element == EL_EXPLOSION)
2083 int graphic = el_act2img(GfxElement[last_jx][last_jy], ACTION_EXPLODING);
2084 int delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2);
2085 int phase = ExplodePhase[last_jx][last_jy] - 1;
2086 int frame = getGraphicAnimationFrame(graphic, phase - delay);
2089 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy), graphic, frame);
2092 /* ----------------------------------------------------------------------- */
2093 /* draw elements the player is just walking/passing through/under */
2094 /* ----------------------------------------------------------------------- */
2096 if (player_is_moving)
2098 /* handle the field the player is leaving ... */
2099 if (IS_ACCESSIBLE_INSIDE(last_element))
2100 DrawLevelField(last_jx, last_jy);
2101 else if (IS_ACCESSIBLE_UNDER(last_element))
2102 DrawLevelFieldThruMask(last_jx, last_jy);
2106 /* do not redraw accessible elements if the player is just pushing them */
2107 if (!player_is_moving || !player->is_pushing)
2109 /* ... and the field the player is entering */
2110 if (IS_ACCESSIBLE_INSIDE(element))
2111 DrawLevelField(jx, jy);
2112 else if (IS_ACCESSIBLE_UNDER(element))
2113 DrawLevelFieldThruMask(jx, jy);
2119 /* !!! I have forgotton what this should be good for !!! */
2120 /* !!! causes player being visible when pushing from within tubes !!! */
2121 if (!player->is_pushing)
2124 /* ... and the field the player is entering */
2125 if (IS_ACCESSIBLE_INSIDE(element))
2126 DrawLevelField(jx, jy);
2127 else if (IS_ACCESSIBLE_UNDER(element))
2128 DrawLevelFieldThruMask(jx, jy);
2132 if (setup.direct_draw)
2134 int dst_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
2135 int dst_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
2136 int x_size = TILEX * (1 + ABS(jx - last_jx));
2137 int y_size = TILEY * (1 + ABS(jy - last_jy));
2139 BlitBitmap(drawto_field, window,
2140 dst_x, dst_y, x_size, y_size, dst_x, dst_y);
2141 SetDrawtoField(DRAW_DIRECT);
2144 MarkTileDirty(sx, sy);
2147 /* ------------------------------------------------------------------------- */
2149 void WaitForEventToContinue()
2151 boolean still_wait = TRUE;
2153 /* simulate releasing mouse button over last gadget, if still pressed */
2155 HandleGadgets(-1, -1, 0);
2157 button_status = MB_RELEASED;
2169 case EVENT_BUTTONPRESS:
2170 case EVENT_KEYPRESS:
2174 case EVENT_KEYRELEASE:
2175 ClearPlayerAction();
2179 HandleOtherEvents(&event);
2183 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2190 /* don't eat all CPU time */
2195 #define MAX_REQUEST_LINES 13
2196 #define MAX_REQUEST_LINE_FONT1_LEN 7
2197 #define MAX_REQUEST_LINE_FONT2_LEN 10
2199 boolean Request(char *text, unsigned int req_state)
2201 int mx, my, ty, result = -1;
2202 unsigned int old_door_state;
2203 int last_game_status = game_status; /* save current game status */
2204 int max_request_line_len = MAX_REQUEST_LINE_FONT1_LEN;
2205 int font_nr = FONT_TEXT_2;
2206 int max_word_len = 0;
2209 for (text_ptr = text; *text_ptr; text_ptr++)
2211 max_word_len = (*text_ptr != ' ' ? max_word_len + 1 : 0);
2213 if (max_word_len > MAX_REQUEST_LINE_FONT1_LEN)
2215 max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
2216 font_nr = FONT_LEVEL_NUMBER;
2223 /* disable deactivated drawing when quick-loading level tape recording */
2224 if (tape.playing && tape.deactivate_display)
2225 TapeDeactivateDisplayOff(TRUE);
2229 SetMouseCursor(CURSOR_DEFAULT);
2232 #if defined(NETWORK_AVALIABLE)
2233 /* pause network game while waiting for request to answer */
2234 if (options.network &&
2235 game_status == GAME_MODE_PLAYING &&
2236 req_state & REQUEST_WAIT_FOR_INPUT)
2237 SendToServer_PausePlaying();
2240 old_door_state = GetDoorState();
2242 /* simulate releasing mouse button over last gadget, if still pressed */
2244 HandleGadgets(-1, -1, 0);
2248 if (old_door_state & DOOR_OPEN_1)
2250 CloseDoor(DOOR_CLOSE_1);
2252 /* save old door content */
2253 BlitBitmap(bitmap_db_door, bitmap_db_door,
2254 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
2255 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
2258 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
2260 /* clear door drawing field */
2261 DrawBackground(DX, DY, DXSIZE, DYSIZE);
2263 /* force DOOR font on preview level */
2264 game_status = GAME_MODE_PSEUDO_DOOR;
2266 /* write text for request */
2267 for (ty = 0; ty < MAX_REQUEST_LINES; ty++)
2269 char text_line[max_request_line_len + 1];
2275 for (tl = 0, tx = 0; tx < max_request_line_len; tl++, tx++)
2278 if (!tc || tc == ' ')
2289 strncpy(text_line, text, tl);
2292 DrawText(DX + (DXSIZE - tl * getFontWidth(font_nr)) / 2,
2293 DY + 8 + ty * (getFontHeight(font_nr) + 2),
2294 text_line, font_nr);
2296 text += tl + (tc == ' ' ? 1 : 0);
2299 game_status = last_game_status; /* restore current game status */
2301 if (req_state & REQ_ASK)
2303 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
2304 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
2306 else if (req_state & REQ_CONFIRM)
2308 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
2310 else if (req_state & REQ_PLAYER)
2312 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
2313 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
2314 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
2315 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
2318 /* copy request gadgets to door backbuffer */
2319 BlitBitmap(drawto, bitmap_db_door,
2320 DX, DY, DXSIZE, DYSIZE,
2321 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2323 OpenDoor(DOOR_OPEN_1);
2329 if (!(req_state & REQUEST_WAIT_FOR_INPUT))
2331 SetDrawBackgroundMask(REDRAW_FIELD);
2336 if (game_status != GAME_MODE_MAIN)
2339 button_status = MB_RELEASED;
2341 request_gadget_id = -1;
2343 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
2346 SetMouseCursor(CURSOR_DEFAULT);
2359 case EVENT_BUTTONPRESS:
2360 case EVENT_BUTTONRELEASE:
2361 case EVENT_MOTIONNOTIFY:
2363 if (event.type == EVENT_MOTIONNOTIFY)
2365 if (!PointerInWindow(window))
2366 continue; /* window and pointer are on different screens */
2371 motion_status = TRUE;
2372 mx = ((MotionEvent *) &event)->x;
2373 my = ((MotionEvent *) &event)->y;
2377 motion_status = FALSE;
2378 mx = ((ButtonEvent *) &event)->x;
2379 my = ((ButtonEvent *) &event)->y;
2380 if (event.type == EVENT_BUTTONPRESS)
2381 button_status = ((ButtonEvent *) &event)->button;
2383 button_status = MB_RELEASED;
2386 /* this sets 'request_gadget_id' */
2387 HandleGadgets(mx, my, button_status);
2389 switch(request_gadget_id)
2391 case TOOL_CTRL_ID_YES:
2394 case TOOL_CTRL_ID_NO:
2397 case TOOL_CTRL_ID_CONFIRM:
2398 result = TRUE | FALSE;
2401 case TOOL_CTRL_ID_PLAYER_1:
2404 case TOOL_CTRL_ID_PLAYER_2:
2407 case TOOL_CTRL_ID_PLAYER_3:
2410 case TOOL_CTRL_ID_PLAYER_4:
2421 case EVENT_KEYPRESS:
2422 switch(GetEventKey((KeyEvent *)&event, TRUE))
2435 if (req_state & REQ_PLAYER)
2439 case EVENT_KEYRELEASE:
2440 ClearPlayerAction();
2444 HandleOtherEvents(&event);
2448 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2450 int joy = AnyJoystick();
2452 if (joy & JOY_BUTTON_1)
2454 else if (joy & JOY_BUTTON_2)
2460 /* don't eat all CPU time */
2464 if (game_status != GAME_MODE_MAIN)
2469 if (!(req_state & REQ_STAY_OPEN))
2471 CloseDoor(DOOR_CLOSE_1);
2473 if (((old_door_state & DOOR_OPEN_1) && !(req_state & REQ_STAY_CLOSED)) ||
2474 (req_state & REQ_REOPEN))
2475 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
2480 SetDrawBackgroundMask(REDRAW_FIELD);
2482 #if defined(NETWORK_AVALIABLE)
2483 /* continue network game after request */
2484 if (options.network &&
2485 game_status == GAME_MODE_PLAYING &&
2486 req_state & REQUEST_WAIT_FOR_INPUT)
2487 SendToServer_ContinuePlaying();
2491 /* restore deactivated drawing when quick-loading level tape recording */
2492 if (tape.playing && tape.deactivate_display)
2493 TapeDeactivateDisplayOn();
2499 unsigned int OpenDoor(unsigned int door_state)
2501 if (door_state & DOOR_COPY_BACK)
2503 if (door_state & DOOR_OPEN_1)
2504 BlitBitmap(bitmap_db_door, bitmap_db_door,
2505 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
2506 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2508 if (door_state & DOOR_OPEN_2)
2509 BlitBitmap(bitmap_db_door, bitmap_db_door,
2510 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY2, VXSIZE, VYSIZE,
2511 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2513 door_state &= ~DOOR_COPY_BACK;
2516 return MoveDoor(door_state);
2519 unsigned int CloseDoor(unsigned int door_state)
2521 unsigned int old_door_state = GetDoorState();
2523 if (!(door_state & DOOR_NO_COPY_BACK))
2525 if (old_door_state & DOOR_OPEN_1)
2526 BlitBitmap(backbuffer, bitmap_db_door,
2527 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2529 if (old_door_state & DOOR_OPEN_2)
2530 BlitBitmap(backbuffer, bitmap_db_door,
2531 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2533 door_state &= ~DOOR_NO_COPY_BACK;
2536 return MoveDoor(door_state);
2539 unsigned int GetDoorState()
2541 return MoveDoor(DOOR_GET_STATE);
2544 unsigned int SetDoorState(unsigned int door_state)
2546 return MoveDoor(door_state | DOOR_SET_STATE);
2549 unsigned int MoveDoor(unsigned int door_state)
2551 static int door1 = DOOR_OPEN_1;
2552 static int door2 = DOOR_CLOSE_2;
2553 unsigned long door_delay = 0;
2554 unsigned long door_delay_value;
2557 if (door_state == DOOR_GET_STATE)
2558 return(door1 | door2);
2560 if (door_state & DOOR_SET_STATE)
2562 if (door_state & DOOR_ACTION_1)
2563 door1 = door_state & DOOR_ACTION_1;
2564 if (door_state & DOOR_ACTION_2)
2565 door2 = door_state & DOOR_ACTION_2;
2567 return(door1 | door2);
2570 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2571 door_state &= ~DOOR_OPEN_1;
2572 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2573 door_state &= ~DOOR_CLOSE_1;
2574 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2575 door_state &= ~DOOR_OPEN_2;
2576 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2577 door_state &= ~DOOR_CLOSE_2;
2579 door_delay_value = (door_state & DOOR_ACTION_1 ? door_1.step_delay :
2582 if (setup.quick_doors)
2584 stepsize = 20; /* must be choosen to always draw last frame */
2585 door_delay_value = 0;
2588 StopSound(SND_DOOR_OPENING);
2589 StopSound(SND_DOOR_CLOSING);
2593 if (global.autoplay_leveldir)
2595 door_state |= DOOR_NO_DELAY;
2596 door_state &= ~DOOR_CLOSE_ALL;
2599 if (door_state & DOOR_ACTION)
2601 boolean door_1_done = !(door_state & DOOR_ACTION_1);
2602 boolean door_2_done = !(door_state & DOOR_ACTION_2);
2603 int start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2604 int end = (door_state & DOOR_ACTION_1 &&
2605 door_1.anim_mode == ANIM_VERTICAL ? DYSIZE : DXSIZE);
2608 if (!(door_state & DOOR_NO_DELAY) && !setup.quick_doors)
2610 /* opening door sound has priority over simultaneously closing door */
2611 if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
2612 PlaySoundStereo(SND_DOOR_OPENING, SOUND_MIDDLE);
2613 else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
2614 PlaySoundStereo(SND_DOOR_CLOSING, SOUND_MIDDLE);
2617 for (x = start; x <= end && !(door_1_done && door_2_done); x += stepsize)
2619 Bitmap *bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2620 GC gc = bitmap->stored_clip_gc;
2622 if (door_state & DOOR_ACTION_1)
2624 int a = MIN(x * door_1.step_offset, end);
2625 int i = (door_state & DOOR_OPEN_1 ? end - a : a);
2629 BlitBitmap(bitmap_db_door, drawto,
2630 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i / 2,
2631 DXSIZE, DYSIZE - i / 2, DX, DY);
2633 ClearRectangle(drawto, DX, DY + DYSIZE - i / 2, DXSIZE, i / 2);
2636 if (door_1.anim_mode == ANIM_HORIZONTAL && x <= DXSIZE)
2638 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
2639 int dst1_x = DX + DXSIZE - i, dst1_y = DY;
2640 int src2_x = DXSIZE - i, src2_y = DOOR_GFX_PAGEY1;
2641 int dst2_x = DX, dst2_y = DY;
2642 int width = i, height = DYSIZE;
2644 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2645 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2648 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2649 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2652 else if (door_1.anim_mode == ANIM_VERTICAL && x <= DYSIZE)
2654 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
2655 int dst1_x = DX, dst1_y = DY + DYSIZE - i;
2656 int src2_x = 0, src2_y = DOOR_GFX_PAGEY1 + DYSIZE - i;
2657 int dst2_x = DX, dst2_y = DY;
2658 int width = DXSIZE, height = i;
2660 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2661 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2664 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2665 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2668 else if (x <= DXSIZE) /* ANIM_DEFAULT */
2670 int j = (door_1.anim_mode == ANIM_DEFAULT ? (DXSIZE - i) / 3 : 0);
2672 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2673 BlitBitmapMasked(bitmap, drawto,
2674 DXSIZE, DOOR_GFX_PAGEY1, i, 77,
2675 DX + DXSIZE - i, DY + j);
2676 BlitBitmapMasked(bitmap, drawto,
2677 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
2678 DX + DXSIZE - i, DY + 140 + j);
2679 SetClipOrigin(bitmap, gc, DX - DXSIZE + i,
2680 DY - (DOOR_GFX_PAGEY1 + j));
2681 BlitBitmapMasked(bitmap, drawto,
2682 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
2684 BlitBitmapMasked(bitmap, drawto,
2685 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
2688 BlitBitmapMasked(bitmap, drawto,
2689 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2691 BlitBitmapMasked(bitmap, drawto,
2692 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2694 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2695 BlitBitmapMasked(bitmap, drawto,
2696 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2697 DX + DXSIZE - i, DY + 77 + j);
2698 BlitBitmapMasked(bitmap, drawto,
2699 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2700 DX + DXSIZE - i, DY + 203 + j);
2703 redraw_mask |= REDRAW_DOOR_1;
2704 door_1_done = (a == end);
2707 if (door_state & DOOR_ACTION_2)
2709 int a = MIN(x * door_2.step_offset, VXSIZE);
2710 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - a : a);
2714 BlitBitmap(bitmap_db_door, drawto,
2715 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i / 2,
2716 VXSIZE, VYSIZE - i / 2, VX, VY);
2718 ClearRectangle(drawto, VX, VY + VYSIZE - i / 2, VXSIZE, i / 2);
2721 if (door_2.anim_mode == ANIM_HORIZONTAL && x <= VXSIZE)
2723 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
2724 int dst1_x = VX + VXSIZE - i, dst1_y = VY;
2725 int src2_x = VXSIZE - i, src2_y = DOOR_GFX_PAGEY2;
2726 int dst2_x = VX, dst2_y = VY;
2727 int width = i, height = VYSIZE;
2729 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2730 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2733 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2734 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2737 else if (door_2.anim_mode == ANIM_VERTICAL && x <= VYSIZE)
2739 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
2740 int dst1_x = VX, dst1_y = VY + VYSIZE - i;
2741 int src2_x = 0, src2_y = DOOR_GFX_PAGEY2 + VYSIZE - i;
2742 int dst2_x = VX, dst2_y = VY;
2743 int width = VXSIZE, height = i;
2745 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2746 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2749 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2750 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2753 else if (x <= VXSIZE) /* ANIM_DEFAULT */
2755 int j = (door_2.anim_mode == ANIM_DEFAULT ? (VXSIZE - i) / 3 : 0);
2757 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2758 BlitBitmapMasked(bitmap, drawto,
2759 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
2760 VX + VXSIZE - i, VY + j);
2761 SetClipOrigin(bitmap, gc,
2762 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2763 BlitBitmapMasked(bitmap, drawto,
2764 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
2767 BlitBitmapMasked(bitmap, drawto,
2768 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2769 i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
2770 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2771 BlitBitmapMasked(bitmap, drawto,
2772 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2774 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2777 redraw_mask |= REDRAW_DOOR_2;
2778 door_2_done = (a == VXSIZE);
2783 if (game_status == GAME_MODE_MAIN)
2786 if (!(door_state & DOOR_NO_DELAY))
2787 WaitUntilDelayReached(&door_delay, door_delay_value);
2792 if (setup.quick_doors)
2794 StopSound(SND_DOOR_OPENING);
2795 StopSound(SND_DOOR_CLOSING);
2799 if (door_state & DOOR_ACTION_1)
2800 door1 = door_state & DOOR_ACTION_1;
2801 if (door_state & DOOR_ACTION_2)
2802 door2 = door_state & DOOR_ACTION_2;
2804 return (door1 | door2);
2807 void DrawSpecialEditorDoor()
2809 /* draw bigger toolbox window */
2810 BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
2811 DOOR_GFX_PAGEX7, 0, EXSIZE + 8, 8,
2813 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2814 EX - 4, VY - 4, EXSIZE + 8, EYSIZE - VYSIZE + 4,
2817 redraw_mask |= REDRAW_ALL;
2820 void UndrawSpecialEditorDoor()
2822 /* draw normal tape recorder window */
2823 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2824 EX - 4, EY - 12, EXSIZE + 8, EYSIZE - VYSIZE + 12,
2827 redraw_mask |= REDRAW_ALL;
2831 /* ---------- new tool button stuff ---------------------------------------- */
2833 /* graphic position values for tool buttons */
2834 #define TOOL_BUTTON_YES_XPOS 2
2835 #define TOOL_BUTTON_YES_YPOS 250
2836 #define TOOL_BUTTON_YES_GFX_YPOS 0
2837 #define TOOL_BUTTON_YES_XSIZE 46
2838 #define TOOL_BUTTON_YES_YSIZE 28
2839 #define TOOL_BUTTON_NO_XPOS 52
2840 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2841 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2842 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2843 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2844 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2845 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2846 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2847 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2848 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2849 #define TOOL_BUTTON_PLAYER_XSIZE 30
2850 #define TOOL_BUTTON_PLAYER_YSIZE 30
2851 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2852 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2853 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2854 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2855 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2856 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2857 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2858 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2859 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2860 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2861 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2862 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2863 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2864 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2865 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2866 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2867 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2868 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2869 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2870 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2879 } toolbutton_info[NUM_TOOL_BUTTONS] =
2882 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2883 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2884 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2889 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2890 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2891 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2896 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2897 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2898 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2899 TOOL_CTRL_ID_CONFIRM,
2903 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2904 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2905 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2906 TOOL_CTRL_ID_PLAYER_1,
2910 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2911 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2912 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2913 TOOL_CTRL_ID_PLAYER_2,
2917 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2918 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2919 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2920 TOOL_CTRL_ID_PLAYER_3,
2924 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2925 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2926 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2927 TOOL_CTRL_ID_PLAYER_4,
2932 void CreateToolButtons()
2936 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2938 Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2939 Bitmap *deco_bitmap = None;
2940 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2941 struct GadgetInfo *gi;
2942 unsigned long event_mask;
2943 int gd_xoffset, gd_yoffset;
2944 int gd_x1, gd_x2, gd_y;
2947 event_mask = GD_EVENT_RELEASED;
2949 gd_xoffset = toolbutton_info[i].xpos;
2950 gd_yoffset = toolbutton_info[i].ypos;
2951 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2952 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2953 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2955 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2957 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
2959 getMiniGraphicSource(PLAYER_NR_GFX(IMG_PLAYER_1, player_nr),
2960 &deco_bitmap, &deco_x, &deco_y);
2961 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2962 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2965 gi = CreateGadget(GDI_CUSTOM_ID, id,
2966 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2967 GDI_X, DX + toolbutton_info[i].x,
2968 GDI_Y, DY + toolbutton_info[i].y,
2969 GDI_WIDTH, toolbutton_info[i].width,
2970 GDI_HEIGHT, toolbutton_info[i].height,
2971 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2972 GDI_STATE, GD_BUTTON_UNPRESSED,
2973 GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
2974 GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
2975 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
2976 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2977 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2978 GDI_DECORATION_SHIFTING, 1, 1,
2979 GDI_EVENT_MASK, event_mask,
2980 GDI_CALLBACK_ACTION, HandleToolButtons,
2984 Error(ERR_EXIT, "cannot create gadget");
2986 tool_gadget[id] = gi;
2990 void FreeToolButtons()
2994 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2995 FreeGadget(tool_gadget[i]);
2998 static void UnmapToolButtons()
3002 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
3003 UnmapGadget(tool_gadget[i]);
3006 static void HandleToolButtons(struct GadgetInfo *gi)
3008 request_gadget_id = gi->custom_id;
3013 static struct Mapping_EM_to_RND_object
3016 boolean is_rnd_to_em_mapping; /* unique mapping EM <-> RND */
3017 boolean is_backside; /* backside of moving element */
3023 em_object_mapping_list[] =
3026 Xblank, TRUE, FALSE,
3030 Yacid_splash_eB, FALSE, FALSE,
3031 EL_ACID_SPLASH_RIGHT, -1, -1
3034 Yacid_splash_wB, FALSE, FALSE,
3035 EL_ACID_SPLASH_LEFT, -1, -1
3038 #ifdef EM_ENGINE_BAD_ROLL
3040 Xstone_force_e, FALSE, FALSE,
3041 EL_ROCK, -1, MV_BIT_RIGHT
3044 Xstone_force_w, FALSE, FALSE,
3045 EL_ROCK, -1, MV_BIT_LEFT
3048 Xnut_force_e, FALSE, FALSE,
3049 EL_NUT, -1, MV_BIT_RIGHT
3052 Xnut_force_w, FALSE, FALSE,
3053 EL_NUT, -1, MV_BIT_LEFT
3056 Xspring_force_e, FALSE, FALSE,
3057 EL_SPRING, -1, MV_BIT_RIGHT
3060 Xspring_force_w, FALSE, FALSE,
3061 EL_SPRING, -1, MV_BIT_LEFT
3064 Xemerald_force_e, FALSE, FALSE,
3065 EL_EMERALD, -1, MV_BIT_RIGHT
3068 Xemerald_force_w, FALSE, FALSE,
3069 EL_EMERALD, -1, MV_BIT_LEFT
3072 Xdiamond_force_e, FALSE, FALSE,
3073 EL_DIAMOND, -1, MV_BIT_RIGHT
3076 Xdiamond_force_w, FALSE, FALSE,
3077 EL_DIAMOND, -1, MV_BIT_LEFT
3080 Xbomb_force_e, FALSE, FALSE,
3081 EL_BOMB, -1, MV_BIT_RIGHT
3084 Xbomb_force_w, FALSE, FALSE,
3085 EL_BOMB, -1, MV_BIT_LEFT
3087 #endif /* EM_ENGINE_BAD_ROLL */
3090 Xstone, TRUE, FALSE,
3094 Xstone_pause, FALSE, FALSE,
3098 Xstone_fall, FALSE, FALSE,
3102 Ystone_s, FALSE, FALSE,
3103 EL_ROCK, ACTION_FALLING, -1
3106 Ystone_sB, FALSE, TRUE,
3107 EL_ROCK, ACTION_FALLING, -1
3110 Ystone_e, FALSE, FALSE,
3111 EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT
3114 Ystone_eB, FALSE, TRUE,
3115 EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT
3118 Ystone_w, FALSE, FALSE,
3119 EL_ROCK, ACTION_MOVING, MV_BIT_LEFT
3122 Ystone_wB, FALSE, TRUE,
3123 EL_ROCK, ACTION_MOVING, MV_BIT_LEFT
3130 Xnut_pause, FALSE, FALSE,
3134 Xnut_fall, FALSE, FALSE,
3138 Ynut_s, FALSE, FALSE,
3139 EL_NUT, ACTION_FALLING, -1
3142 Ynut_sB, FALSE, TRUE,
3143 EL_NUT, ACTION_FALLING, -1
3146 Ynut_e, FALSE, FALSE,
3147 EL_NUT, ACTION_MOVING, MV_BIT_RIGHT
3150 Ynut_eB, FALSE, TRUE,
3151 EL_NUT, ACTION_MOVING, MV_BIT_RIGHT
3154 Ynut_w, FALSE, FALSE,
3155 EL_NUT, ACTION_MOVING, MV_BIT_LEFT
3158 Ynut_wB, FALSE, TRUE,
3159 EL_NUT, ACTION_MOVING, MV_BIT_LEFT
3162 Xbug_n, TRUE, FALSE,
3166 Xbug_e, TRUE, FALSE,
3167 EL_BUG_RIGHT, -1, -1
3170 Xbug_s, TRUE, FALSE,
3174 Xbug_w, TRUE, FALSE,
3178 Xbug_gon, FALSE, FALSE,
3182 Xbug_goe, FALSE, FALSE,
3183 EL_BUG_RIGHT, -1, -1
3186 Xbug_gos, FALSE, FALSE,
3190 Xbug_gow, FALSE, FALSE,
3194 Ybug_n, FALSE, FALSE,
3195 EL_BUG, ACTION_MOVING, MV_BIT_UP
3198 Ybug_nB, FALSE, TRUE,
3199 EL_BUG, ACTION_MOVING, MV_BIT_UP
3202 Ybug_e, FALSE, FALSE,
3203 EL_BUG, ACTION_MOVING, MV_BIT_RIGHT
3206 Ybug_eB, FALSE, TRUE,
3207 EL_BUG, ACTION_MOVING, MV_BIT_RIGHT
3210 Ybug_s, FALSE, FALSE,
3211 EL_BUG, ACTION_MOVING, MV_BIT_DOWN
3214 Ybug_sB, FALSE, TRUE,
3215 EL_BUG, ACTION_MOVING, MV_BIT_DOWN
3218 Ybug_w, FALSE, FALSE,
3219 EL_BUG, ACTION_MOVING, MV_BIT_LEFT
3222 Ybug_wB, FALSE, TRUE,
3223 EL_BUG, ACTION_MOVING, MV_BIT_LEFT
3226 Ybug_w_n, FALSE, FALSE,
3227 EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_UP
3230 Ybug_n_e, FALSE, FALSE,
3231 EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3234 Ybug_e_s, FALSE, FALSE,
3235 EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
3238 Ybug_s_w, FALSE, FALSE,
3239 EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3242 Ybug_e_n, FALSE, FALSE,
3243 EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
3246 Ybug_s_e, FALSE, FALSE,
3247 EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3250 Ybug_w_s, FALSE, FALSE,
3251 EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
3254 Ybug_n_w, FALSE, FALSE,
3255 EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3258 Ybug_stone, FALSE, FALSE,
3259 EL_BUG, ACTION_SMASHED_BY_ROCK, -1
3262 Ybug_spring, FALSE, FALSE,
3263 EL_BUG, ACTION_SMASHED_BY_SPRING, -1
3266 Xtank_n, TRUE, FALSE,
3267 EL_SPACESHIP_UP, -1, -1
3270 Xtank_e, TRUE, FALSE,
3271 EL_SPACESHIP_RIGHT, -1, -1
3274 Xtank_s, TRUE, FALSE,
3275 EL_SPACESHIP_DOWN, -1, -1
3278 Xtank_w, TRUE, FALSE,
3279 EL_SPACESHIP_LEFT, -1, -1
3282 Xtank_gon, FALSE, FALSE,
3283 EL_SPACESHIP_UP, -1, -1
3286 Xtank_goe, FALSE, FALSE,
3287 EL_SPACESHIP_RIGHT, -1, -1
3290 Xtank_gos, FALSE, FALSE,
3291 EL_SPACESHIP_DOWN, -1, -1
3294 Xtank_gow, FALSE, FALSE,
3295 EL_SPACESHIP_LEFT, -1, -1
3298 Ytank_n, FALSE, FALSE,
3299 EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP
3302 Ytank_nB, FALSE, TRUE,
3303 EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP
3306 Ytank_e, FALSE, FALSE,
3307 EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT
3310 Ytank_eB, FALSE, TRUE,
3311 EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT
3314 Ytank_s, FALSE, FALSE,
3315 EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN
3318 Ytank_sB, FALSE, TRUE,
3319 EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN
3322 Ytank_w, FALSE, FALSE,
3323 EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT
3326 Ytank_wB, FALSE, TRUE,
3327 EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT
3330 Ytank_w_n, FALSE, FALSE,
3331 EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_UP
3334 Ytank_n_e, FALSE, FALSE,
3335 EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3338 Ytank_e_s, FALSE, FALSE,
3339 EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
3342 Ytank_s_w, FALSE, FALSE,
3343 EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3346 Ytank_e_n, FALSE, FALSE,
3347 EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
3350 Ytank_s_e, FALSE, FALSE,
3351 EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3354 Ytank_w_s, FALSE, FALSE,
3355 EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
3358 Ytank_n_w, FALSE, FALSE,
3359 EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3362 Ytank_stone, FALSE, FALSE,
3363 EL_SPACESHIP, ACTION_SMASHED_BY_ROCK, -1
3366 Ytank_spring, FALSE, FALSE,
3367 EL_SPACESHIP, ACTION_SMASHED_BY_SPRING, -1
3370 Xandroid, TRUE, FALSE,
3371 EL_EMC_ANDROID, ACTION_ACTIVE, -1
3374 Xandroid_1_n, FALSE, FALSE,
3375 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_UP
3378 Xandroid_2_n, FALSE, FALSE,
3379 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_UP
3382 Xandroid_1_e, FALSE, FALSE,
3383 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_RIGHT
3386 Xandroid_2_e, FALSE, FALSE,
3387 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_RIGHT
3390 Xandroid_1_w, FALSE, FALSE,
3391 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_LEFT
3394 Xandroid_2_w, FALSE, FALSE,
3395 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_LEFT
3398 Xandroid_1_s, FALSE, FALSE,
3399 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_DOWN
3402 Xandroid_2_s, FALSE, FALSE,
3403 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_DOWN
3406 Yandroid_n, FALSE, FALSE,
3407 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_UP
3410 Yandroid_nB, FALSE, TRUE,
3411 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_UP
3414 Yandroid_ne, FALSE, FALSE,
3415 EL_EMC_ANDROID, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3418 Yandroid_neB, FALSE, TRUE,
3419 EL_EMC_ANDROID, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3422 Yandroid_e, FALSE, FALSE,
3423 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_RIGHT
3426 Yandroid_eB, FALSE, TRUE,
3427 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_RIGHT
3430 Yandroid_se, FALSE, FALSE,
3431 EL_EMC_ANDROID, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3434 Yandroid_seB, FALSE, TRUE,
3435 EL_EMC_ANDROID, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3438 Yandroid_s, FALSE, FALSE,
3439 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_DOWN
3442 Yandroid_sB, FALSE, TRUE,
3443 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_DOWN
3446 Yandroid_sw, FALSE, FALSE,
3447 EL_EMC_ANDROID, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3450 Yandroid_swB, FALSE, TRUE,
3451 EL_EMC_ANDROID, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3454 Yandroid_w, FALSE, FALSE,
3455 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_LEFT
3458 Yandroid_wB, FALSE, TRUE,
3459 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_LEFT
3462 Yandroid_nw, FALSE, FALSE,
3463 EL_EMC_ANDROID, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3466 Yandroid_nwB, FALSE, TRUE,
3467 EL_EMC_ANDROID, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3470 Xspring, TRUE, FALSE,
3474 Xspring_pause, FALSE, FALSE,
3478 Xspring_e, FALSE, FALSE,
3482 Xspring_w, FALSE, FALSE,
3486 Xspring_fall, FALSE, FALSE,
3490 Yspring_s, FALSE, FALSE,
3491 EL_SPRING, ACTION_FALLING, -1
3494 Yspring_sB, FALSE, TRUE,
3495 EL_SPRING, ACTION_FALLING, -1
3498 Yspring_e, FALSE, FALSE,
3499 EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT
3502 Yspring_eB, FALSE, TRUE,
3503 EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT
3506 Yspring_w, FALSE, FALSE,
3507 EL_SPRING, ACTION_MOVING, MV_BIT_LEFT
3510 Yspring_wB, FALSE, TRUE,
3511 EL_SPRING, ACTION_MOVING, MV_BIT_LEFT
3514 Yspring_kill_e, FALSE, FALSE,
3515 EL_ROBOT, ACTION_SLURPED_BY_SPRING, MV_BIT_RIGHT
3518 Yspring_kill_eB, FALSE, TRUE,
3519 EL_ROBOT, ACTION_SLURPED_BY_SPRING, MV_BIT_RIGHT
3522 Yspring_kill_w, FALSE, FALSE,
3523 EL_ROBOT, ACTION_SLURPED_BY_SPRING, MV_BIT_LEFT
3526 Yspring_kill_wB, FALSE, TRUE,
3527 EL_ROBOT, ACTION_SLURPED_BY_SPRING, MV_BIT_LEFT
3530 Xeater_n, TRUE, FALSE,
3534 Xeater_e, FALSE, FALSE,
3538 Xeater_w, FALSE, FALSE,
3542 Xeater_s, FALSE, FALSE,
3546 Yeater_n, FALSE, FALSE,
3547 EL_YAMYAM, ACTION_MOVING, MV_BIT_UP
3550 Yeater_nB, FALSE, TRUE,
3551 EL_YAMYAM, ACTION_MOVING, MV_BIT_UP
3554 Yeater_e, FALSE, FALSE,
3555 EL_YAMYAM, ACTION_MOVING, MV_BIT_RIGHT
3558 Yeater_eB, FALSE, TRUE,
3559 EL_YAMYAM, ACTION_MOVING, MV_BIT_RIGHT
3562 Yeater_s, FALSE, FALSE,
3563 EL_YAMYAM, ACTION_MOVING, MV_BIT_DOWN
3566 Yeater_sB, FALSE, TRUE,
3567 EL_YAMYAM, ACTION_MOVING, MV_BIT_DOWN
3570 Yeater_w, FALSE, FALSE,
3571 EL_YAMYAM, ACTION_MOVING, MV_BIT_LEFT
3574 Yeater_wB, FALSE, TRUE,
3575 EL_YAMYAM, ACTION_MOVING, MV_BIT_LEFT
3578 Yeater_stone, FALSE, FALSE,
3579 EL_YAMYAM, ACTION_SMASHED_BY_ROCK, -1
3582 Yeater_spring, FALSE, FALSE,
3583 EL_YAMYAM, ACTION_SMASHED_BY_SPRING, -1
3586 Xalien, TRUE, FALSE,
3590 Xalien_pause, FALSE, FALSE,
3594 Yalien_n, FALSE, FALSE,
3595 EL_ROBOT, ACTION_MOVING, MV_BIT_UP
3598 Yalien_nB, FALSE, TRUE,
3599 EL_ROBOT, ACTION_MOVING, MV_BIT_UP
3602 Yalien_e, FALSE, FALSE,
3603 EL_ROBOT, ACTION_MOVING, MV_BIT_RIGHT
3606 Yalien_eB, FALSE, TRUE,
3607 EL_ROBOT, ACTION_MOVING, MV_BIT_RIGHT
3610 Yalien_s, FALSE, FALSE,
3611 EL_ROBOT, ACTION_MOVING, MV_BIT_DOWN
3614 Yalien_sB, FALSE, TRUE,
3615 EL_ROBOT, ACTION_MOVING, MV_BIT_DOWN
3618 Yalien_w, FALSE, FALSE,
3619 EL_ROBOT, ACTION_MOVING, MV_BIT_LEFT
3622 Yalien_wB, FALSE, TRUE,
3623 EL_ROBOT, ACTION_MOVING, MV_BIT_LEFT
3626 Yalien_stone, FALSE, FALSE,
3627 EL_ROBOT, ACTION_SMASHED_BY_ROCK, -1
3630 Yalien_spring, FALSE, FALSE,
3631 EL_ROBOT, ACTION_SMASHED_BY_SPRING, -1
3634 Xemerald, TRUE, FALSE,
3638 Xemerald_pause, FALSE, FALSE,
3642 Xemerald_fall, FALSE, FALSE,
3646 Xemerald_shine, FALSE, FALSE,
3647 EL_EMERALD, ACTION_TWINKLING, -1
3650 Yemerald_s, FALSE, FALSE,
3651 EL_EMERALD, ACTION_FALLING, -1
3654 Yemerald_sB, FALSE, TRUE,
3655 EL_EMERALD, ACTION_FALLING, -1
3658 Yemerald_e, FALSE, FALSE,
3659 EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT
3662 Yemerald_eB, FALSE, TRUE,
3663 EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT
3666 Yemerald_w, FALSE, FALSE,
3667 EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT
3670 Yemerald_wB, FALSE, TRUE,
3671 EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT
3674 Yemerald_eat, FALSE, FALSE,
3675 EL_EMERALD, ACTION_COLLECTING, -1
3678 Yemerald_stone, FALSE, FALSE,
3679 EL_NUT, ACTION_BREAKING, -1
3682 Xdiamond, TRUE, FALSE,
3686 Xdiamond_pause, FALSE, FALSE,
3690 Xdiamond_fall, FALSE, FALSE,
3694 Xdiamond_shine, FALSE, FALSE,
3695 EL_DIAMOND, ACTION_TWINKLING, -1
3698 Ydiamond_s, FALSE, FALSE,
3699 EL_DIAMOND, ACTION_FALLING, -1
3702 Ydiamond_sB, FALSE, TRUE,
3703 EL_DIAMOND, ACTION_FALLING, -1
3706 Ydiamond_e, FALSE, FALSE,
3707 EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT
3710 Ydiamond_eB, FALSE, TRUE,
3711 EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT
3714 Ydiamond_w, FALSE, FALSE,
3715 EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT
3718 Ydiamond_wB, FALSE, TRUE,
3719 EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT
3722 Ydiamond_eat, FALSE, FALSE,
3723 EL_DIAMOND, ACTION_COLLECTING, -1
3726 Ydiamond_stone, FALSE, FALSE,
3727 EL_DIAMOND, ACTION_SMASHED_BY_ROCK, -1
3730 Xdrip_fall, TRUE, FALSE,
3731 EL_AMOEBA_DROP, -1, -1
3734 Xdrip_stretch, FALSE, FALSE,
3735 EL_AMOEBA_DROP, ACTION_FALLING, -1
3738 Xdrip_stretchB, FALSE, TRUE,
3739 EL_AMOEBA_DROP, ACTION_FALLING, -1
3742 Xdrip_eat, FALSE, FALSE,
3743 EL_AMOEBA_DROP, ACTION_GROWING, -1
3746 Ydrip_s1, FALSE, FALSE,
3747 EL_AMOEBA_DROP, ACTION_FALLING, -1
3750 Ydrip_s1B, FALSE, TRUE,
3751 EL_AMOEBA_DROP, ACTION_FALLING, -1
3754 Ydrip_s2, FALSE, FALSE,
3755 EL_AMOEBA_DROP, ACTION_FALLING, -1
3758 Ydrip_s2B, FALSE, TRUE,
3759 EL_AMOEBA_DROP, ACTION_FALLING, -1
3766 Xbomb_pause, FALSE, FALSE,
3770 Xbomb_fall, FALSE, FALSE,
3774 Ybomb_s, FALSE, FALSE,
3775 EL_BOMB, ACTION_FALLING, -1
3778 Ybomb_sB, FALSE, TRUE,
3779 EL_BOMB, ACTION_FALLING, -1
3782 Ybomb_e, FALSE, FALSE,
3783 EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT
3786 Ybomb_eB, FALSE, TRUE,
3787 EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT
3790 Ybomb_w, FALSE, FALSE,
3791 EL_BOMB, ACTION_MOVING, MV_BIT_LEFT
3794 Ybomb_wB, FALSE, TRUE,
3795 EL_BOMB, ACTION_MOVING, MV_BIT_LEFT
3798 Ybomb_eat, FALSE, FALSE,
3799 EL_BOMB, ACTION_SMASHED_BY_ROCK, -1
3802 Xballoon, TRUE, FALSE,
3806 Yballoon_n, FALSE, FALSE,
3807 EL_BALLOON, ACTION_MOVING, MV_BIT_UP
3810 Yballoon_nB, FALSE, TRUE,
3811 EL_BALLOON, ACTION_MOVING, MV_BIT_UP
3814 Yballoon_e, FALSE, FALSE,
3815 EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT
3818 Yballoon_eB, FALSE, TRUE,
3819 EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT
3822 Yballoon_s, FALSE, FALSE,
3823 EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN
3826 Yballoon_sB, FALSE, TRUE,
3827 EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN
3830 Yballoon_w, FALSE, FALSE,
3831 EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT
3834 Yballoon_wB, FALSE, TRUE,
3835 EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT
3838 Xgrass, TRUE, FALSE,
3839 EL_EMC_GRASS, -1, -1
3842 Ygrass_nB, FALSE, FALSE,
3843 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_UP
3846 Ygrass_eB, FALSE, FALSE,
3847 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_RIGHT
3850 Ygrass_sB, FALSE, FALSE,
3851 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_DOWN
3854 Ygrass_wB, FALSE, FALSE,
3855 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_LEFT
3862 Ydirt_nB, FALSE, FALSE,
3863 EL_SAND, ACTION_DIGGING, MV_BIT_UP
3866 Ydirt_eB, FALSE, FALSE,
3867 EL_SAND, ACTION_DIGGING, MV_BIT_RIGHT
3870 Ydirt_sB, FALSE, FALSE,
3871 EL_SAND, ACTION_DIGGING, MV_BIT_DOWN
3874 Ydirt_wB, FALSE, FALSE,
3875 EL_SAND, ACTION_DIGGING, MV_BIT_LEFT
3878 Xacid_ne, TRUE, FALSE,
3879 EL_ACID_POOL_TOPRIGHT, -1, -1
3882 Xacid_se, TRUE, FALSE,
3883 EL_ACID_POOL_BOTTOMRIGHT, -1, -1
3886 Xacid_s, TRUE, FALSE,
3887 EL_ACID_POOL_BOTTOM, -1, -1
3890 Xacid_sw, TRUE, FALSE,
3891 EL_ACID_POOL_BOTTOMLEFT, -1, -1
3894 Xacid_nw, TRUE, FALSE,
3895 EL_ACID_POOL_TOPLEFT, -1, -1
3898 Xacid_1, TRUE, FALSE,
3902 Xacid_2, FALSE, FALSE,
3906 Xacid_3, FALSE, FALSE,
3910 Xacid_4, FALSE, FALSE,
3914 Xacid_5, FALSE, FALSE,
3918 Xacid_6, FALSE, FALSE,
3922 Xacid_7, FALSE, FALSE,
3926 Xacid_8, FALSE, FALSE,
3930 Xball_1, TRUE, FALSE,
3931 EL_EMC_MAGIC_BALL, -1, -1
3934 Xball_1B, FALSE, FALSE,
3935 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
3938 Xball_2, FALSE, FALSE,
3939 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
3942 Xball_2B, FALSE, FALSE,
3943 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
3946 Yball_eat, FALSE, FALSE,
3947 EL_EMC_MAGIC_BALL, ACTION_DROPPING, -1
3950 Ykey_1_eat, FALSE, FALSE,
3951 EL_EM_KEY_1, ACTION_COLLECTING, -1
3954 Ykey_2_eat, FALSE, FALSE,
3955 EL_EM_KEY_2, ACTION_COLLECTING, -1
3958 Ykey_3_eat, FALSE, FALSE,
3959 EL_EM_KEY_3, ACTION_COLLECTING, -1
3962 Ykey_4_eat, FALSE, FALSE,
3963 EL_EM_KEY_4, ACTION_COLLECTING, -1
3966 Ykey_5_eat, FALSE, FALSE,
3967 EL_EM_KEY_5, ACTION_COLLECTING, -1
3970 Ykey_6_eat, FALSE, FALSE,
3971 EL_EM_KEY_6, ACTION_COLLECTING, -1
3974 Ykey_7_eat, FALSE, FALSE,
3975 EL_EM_KEY_7, ACTION_COLLECTING, -1
3978 Ykey_8_eat, FALSE, FALSE,
3979 EL_EM_KEY_8, ACTION_COLLECTING, -1
3982 Ylenses_eat, FALSE, FALSE,
3983 EL_EMC_LENSES, ACTION_COLLECTING, -1
3986 Ymagnify_eat, FALSE, FALSE,
3987 EL_EMC_MAGNIFIER, ACTION_COLLECTING, -1
3990 Ygrass_eat, FALSE, FALSE,
3991 EL_EMC_GRASS, ACTION_SNAPPING, -1
3994 Ydirt_eat, FALSE, FALSE,
3995 EL_SAND, ACTION_SNAPPING, -1
3998 Xgrow_ns, TRUE, FALSE,
3999 EL_EXPANDABLE_WALL_VERTICAL, -1, -1
4002 Ygrow_ns_eat, FALSE, FALSE,
4003 EL_EXPANDABLE_WALL_VERTICAL, ACTION_GROWING, -1
4006 Xgrow_ew, TRUE, FALSE,
4007 EL_EXPANDABLE_WALL_HORIZONTAL, -1, -1
4010 Ygrow_ew_eat, FALSE, FALSE,
4011 EL_EXPANDABLE_WALL_HORIZONTAL, ACTION_GROWING, -1
4014 Xwonderwall, TRUE, FALSE,
4015 EL_MAGIC_WALL, -1, -1
4018 XwonderwallB, FALSE, FALSE,
4019 EL_MAGIC_WALL, ACTION_ACTIVE, -1
4022 Xamoeba_1, TRUE, FALSE,
4023 EL_AMOEBA_DRY, ACTION_OTHER, -1
4026 Xamoeba_2, FALSE, FALSE,
4027 EL_AMOEBA_DRY, ACTION_OTHER, -1
4030 Xamoeba_3, FALSE, FALSE,
4031 EL_AMOEBA_DRY, ACTION_OTHER, -1
4034 Xamoeba_4, FALSE, FALSE,
4035 EL_AMOEBA_DRY, ACTION_OTHER, -1
4038 Xamoeba_5, FALSE, FALSE,
4039 EL_AMOEBA_WET, ACTION_OTHER, -1
4042 Xamoeba_6, FALSE, FALSE,
4043 EL_AMOEBA_WET, ACTION_OTHER, -1
4046 Xamoeba_7, FALSE, FALSE,
4047 EL_AMOEBA_WET, ACTION_OTHER, -1
4050 Xamoeba_8, FALSE, FALSE,
4051 EL_AMOEBA_WET, ACTION_OTHER, -1
4054 Xdoor_1, TRUE, FALSE,
4055 EL_EM_GATE_1, -1, -1
4058 Xdoor_2, TRUE, FALSE,
4059 EL_EM_GATE_2, -1, -1
4062 Xdoor_3, TRUE, FALSE,
4063 EL_EM_GATE_3, -1, -1
4066 Xdoor_4, TRUE, FALSE,
4067 EL_EM_GATE_4, -1, -1
4070 Xdoor_5, TRUE, FALSE,
4071 EL_EM_GATE_5, -1, -1
4074 Xdoor_6, TRUE, FALSE,
4075 EL_EM_GATE_6, -1, -1
4078 Xdoor_7, TRUE, FALSE,
4079 EL_EM_GATE_7, -1, -1
4082 Xdoor_8, TRUE, FALSE,
4083 EL_EM_GATE_8, -1, -1
4086 Xkey_1, TRUE, FALSE,
4090 Xkey_2, TRUE, FALSE,
4094 Xkey_3, TRUE, FALSE,
4098 Xkey_4, TRUE, FALSE,
4102 Xkey_5, TRUE, FALSE,
4106 Xkey_6, TRUE, FALSE,
4110 Xkey_7, TRUE, FALSE,
4114 Xkey_8, TRUE, FALSE,
4118 Xwind_n, TRUE, FALSE,
4119 EL_BALLOON_SWITCH_UP, -1, -1
4122 Xwind_e, TRUE, FALSE,
4123 EL_BALLOON_SWITCH_RIGHT, -1, -1
4126 Xwind_s, TRUE, FALSE,
4127 EL_BALLOON_SWITCH_DOWN, -1, -1
4130 Xwind_w, TRUE, FALSE,
4131 EL_BALLOON_SWITCH_LEFT, -1, -1
4134 Xwind_nesw, TRUE, FALSE,
4135 EL_BALLOON_SWITCH_ANY, -1, -1
4138 Xwind_stop, TRUE, FALSE,
4139 EL_BALLOON_SWITCH_NONE, -1, -1
4143 EL_EXIT_CLOSED, -1, -1
4146 Xexit_1, TRUE, FALSE,
4147 EL_EXIT_OPEN, -1, -1
4150 Xexit_2, FALSE, FALSE,
4151 EL_EXIT_OPEN, -1, -1
4154 Xexit_3, FALSE, FALSE,
4155 EL_EXIT_OPEN, -1, -1
4158 Xdynamite, TRUE, FALSE,
4162 Ydynamite_eat, FALSE, FALSE,
4163 EL_DYNAMITE, ACTION_COLLECTING, -1
4166 Xdynamite_1, TRUE, FALSE,
4167 EL_DYNAMITE_ACTIVE, -1, -1
4170 Xdynamite_2, FALSE, FALSE,
4171 EL_DYNAMITE_ACTIVE, -1, -1
4174 Xdynamite_3, FALSE, FALSE,
4175 EL_DYNAMITE_ACTIVE, -1, -1
4178 Xdynamite_4, FALSE, FALSE,
4179 EL_DYNAMITE_ACTIVE, -1, -1
4182 Xbumper, TRUE, FALSE,
4183 EL_EMC_SPRING_BUMPER, -1, -1
4186 XbumperB, FALSE, FALSE,
4187 EL_EMC_SPRING_BUMPER, ACTION_ACTIVE, -1
4190 Xwheel, TRUE, FALSE,
4191 EL_ROBOT_WHEEL, -1, -1
4194 XwheelB, FALSE, FALSE,
4195 EL_ROBOT_WHEEL, ACTION_ACTIVE, -1
4198 Xswitch, TRUE, FALSE,
4199 EL_EMC_MAGIC_BALL_SWITCH, -1, -1
4202 XswitchB, FALSE, FALSE,
4203 EL_EMC_MAGIC_BALL_SWITCH, ACTION_ACTIVE, -1
4207 EL_QUICKSAND_EMPTY, -1, -1
4210 Xsand_stone, TRUE, FALSE,
4211 EL_QUICKSAND_FULL, -1, -1
4214 Xsand_stonein_1, FALSE, FALSE,
4215 EL_ROCK, ACTION_FILLING, -1
4218 Xsand_stonein_2, FALSE, FALSE,
4219 EL_ROCK, ACTION_FILLING, -1
4222 Xsand_stonein_3, FALSE, FALSE,
4223 EL_ROCK, ACTION_FILLING, -1
4226 Xsand_stonein_4, FALSE, FALSE,
4227 EL_ROCK, ACTION_FILLING, -1
4230 Xsand_stonesand_1, FALSE, FALSE,
4231 EL_QUICKSAND_FULL, -1, -1
4234 Xsand_stonesand_2, FALSE, FALSE,
4235 EL_QUICKSAND_FULL, -1, -1
4238 Xsand_stonesand_3, FALSE, FALSE,
4239 EL_QUICKSAND_FULL, -1, -1
4242 Xsand_stonesand_4, FALSE, FALSE,
4243 EL_QUICKSAND_FULL, -1, -1
4246 Xsand_stoneout_1, FALSE, FALSE,
4247 EL_ROCK, ACTION_EMPTYING, -1
4250 Xsand_stoneout_2, FALSE, FALSE,
4251 EL_ROCK, ACTION_EMPTYING, -1
4254 Xsand_sandstone_1, FALSE, FALSE,
4255 EL_QUICKSAND_FULL, -1, -1
4258 Xsand_sandstone_2, FALSE, FALSE,
4259 EL_QUICKSAND_FULL, -1, -1
4262 Xsand_sandstone_3, FALSE, FALSE,
4263 EL_QUICKSAND_FULL, -1, -1
4266 Xsand_sandstone_4, FALSE, FALSE,
4267 EL_QUICKSAND_FULL, -1, -1
4270 Xplant, TRUE, FALSE,
4271 EL_EMC_PLANT, -1, -1
4274 Yplant, FALSE, FALSE,
4275 EL_EMC_PLANT, -1, -1
4278 Xlenses, TRUE, FALSE,
4279 EL_EMC_LENSES, -1, -1
4282 Xmagnify, TRUE, FALSE,
4283 EL_EMC_MAGNIFIER, -1, -1
4286 Xdripper, TRUE, FALSE,
4287 EL_EMC_DRIPPER, -1, -1
4290 XdripperB, FALSE, FALSE,
4291 EL_EMC_DRIPPER, ACTION_ACTIVE, -1
4294 Xfake_blank, TRUE, FALSE,
4295 EL_INVISIBLE_WALL, -1, -1
4298 Xfake_blankB, FALSE, FALSE,
4299 EL_INVISIBLE_WALL, ACTION_ACTIVE, -1
4302 Xfake_grass, TRUE, FALSE,
4303 EL_EMC_FAKE_GRASS, -1, -1
4306 Xfake_grassB, FALSE, FALSE,
4307 EL_EMC_FAKE_GRASS, ACTION_ACTIVE, -1
4310 Xfake_door_1, TRUE, FALSE,
4311 EL_EM_GATE_1_GRAY, -1, -1
4314 Xfake_door_2, TRUE, FALSE,
4315 EL_EM_GATE_2_GRAY, -1, -1
4318 Xfake_door_3, TRUE, FALSE,
4319 EL_EM_GATE_3_GRAY, -1, -1
4322 Xfake_door_4, TRUE, FALSE,
4323 EL_EM_GATE_4_GRAY, -1, -1
4326 Xfake_door_5, TRUE, FALSE,
4327 EL_EM_GATE_5_GRAY, -1, -1
4330 Xfake_door_6, TRUE, FALSE,
4331 EL_EM_GATE_6_GRAY, -1, -1
4334 Xfake_door_7, TRUE, FALSE,
4335 EL_EM_GATE_7_GRAY, -1, -1
4338 Xfake_door_8, TRUE, FALSE,
4339 EL_EM_GATE_8_GRAY, -1, -1
4342 Xsteel_1, TRUE, FALSE,
4343 EL_STEELWALL, -1, -1
4346 Xsteel_2, TRUE, FALSE,
4347 EL_EMC_STEELWALL_2, -1, -1
4350 Xsteel_3, TRUE, FALSE,
4351 EL_EMC_STEELWALL_3, -1, -1
4354 Xsteel_4, TRUE, FALSE,
4355 EL_EMC_STEELWALL_4, -1, -1
4358 Xwall_1, TRUE, FALSE,
4362 Xwall_2, TRUE, FALSE,
4363 EL_EMC_WALL_14, -1, -1
4366 Xwall_3, TRUE, FALSE,
4367 EL_EMC_WALL_15, -1, -1
4370 Xwall_4, TRUE, FALSE,
4371 EL_EMC_WALL_16, -1, -1
4374 Xround_wall_1, TRUE, FALSE,
4375 EL_WALL_SLIPPERY, -1, -1
4378 Xround_wall_2, TRUE, FALSE,
4379 EL_EMC_WALL_SLIPPERY_2, -1, -1
4382 Xround_wall_3, TRUE, FALSE,
4383 EL_EMC_WALL_SLIPPERY_3, -1, -1
4386 Xround_wall_4, TRUE, FALSE,
4387 EL_EMC_WALL_SLIPPERY_4, -1, -1
4390 Xdecor_1, TRUE, FALSE,
4391 EL_EMC_WALL_8, -1, -1
4394 Xdecor_2, TRUE, FALSE,
4395 EL_EMC_WALL_6, -1, -1
4398 Xdecor_3, TRUE, FALSE,
4399 EL_EMC_WALL_4, -1, -1
4402 Xdecor_4, TRUE, FALSE,
4403 EL_EMC_WALL_7, -1, -1
4406 Xdecor_5, TRUE, FALSE,
4407 EL_EMC_WALL_5, -1, -1
4410 Xdecor_6, TRUE, FALSE,
4411 EL_EMC_WALL_9, -1, -1
4414 Xdecor_7, TRUE, FALSE,
4415 EL_EMC_WALL_10, -1, -1
4418 Xdecor_8, TRUE, FALSE,
4419 EL_EMC_WALL_1, -1, -1
4422 Xdecor_9, TRUE, FALSE,
4423 EL_EMC_WALL_2, -1, -1
4426 Xdecor_10, TRUE, FALSE,
4427 EL_EMC_WALL_3, -1, -1
4430 Xdecor_11, TRUE, FALSE,
4431 EL_EMC_WALL_11, -1, -1
4434 Xdecor_12, TRUE, FALSE,
4435 EL_EMC_WALL_12, -1, -1
4438 Xalpha_0, TRUE, FALSE,
4439 EL_CHAR('0'), -1, -1
4442 Xalpha_1, TRUE, FALSE,
4443 EL_CHAR('1'), -1, -1
4446 Xalpha_2, TRUE, FALSE,
4447 EL_CHAR('2'), -1, -1
4450 Xalpha_3, TRUE, FALSE,
4451 EL_CHAR('3'), -1, -1
4454 Xalpha_4, TRUE, FALSE,
4455 EL_CHAR('4'), -1, -1
4458 Xalpha_5, TRUE, FALSE,
4459 EL_CHAR('5'), -1, -1
4462 Xalpha_6, TRUE, FALSE,
4463 EL_CHAR('6'), -1, -1
4466 Xalpha_7, TRUE, FALSE,
4467 EL_CHAR('7'), -1, -1
4470 Xalpha_8, TRUE, FALSE,
4471 EL_CHAR('8'), -1, -1
4474 Xalpha_9, TRUE, FALSE,
4475 EL_CHAR('9'), -1, -1
4478 Xalpha_excla, TRUE, FALSE,
4479 EL_CHAR('!'), -1, -1
4482 Xalpha_quote, TRUE, FALSE,
4483 EL_CHAR('"'), -1, -1
4486 Xalpha_comma, TRUE, FALSE,
4487 EL_CHAR(','), -1, -1
4490 Xalpha_minus, TRUE, FALSE,
4491 EL_CHAR('-'), -1, -1
4494 Xalpha_perio, TRUE, FALSE,
4495 EL_CHAR('.'), -1, -1
4498 Xalpha_colon, TRUE, FALSE,
4499 EL_CHAR(':'), -1, -1
4502 Xalpha_quest, TRUE, FALSE,
4503 EL_CHAR('?'), -1, -1
4506 Xalpha_a, TRUE, FALSE,
4507 EL_CHAR('A'), -1, -1
4510 Xalpha_b, TRUE, FALSE,
4511 EL_CHAR('B'), -1, -1
4514 Xalpha_c, TRUE, FALSE,
4515 EL_CHAR('C'), -1, -1
4518 Xalpha_d, TRUE, FALSE,
4519 EL_CHAR('D'), -1, -1
4522 Xalpha_e, TRUE, FALSE,
4523 EL_CHAR('E'), -1, -1
4526 Xalpha_f, TRUE, FALSE,
4527 EL_CHAR('F'), -1, -1
4530 Xalpha_g, TRUE, FALSE,
4531 EL_CHAR('G'), -1, -1
4534 Xalpha_h, TRUE, FALSE,
4535 EL_CHAR('H'), -1, -1
4538 Xalpha_i, TRUE, FALSE,
4539 EL_CHAR('I'), -1, -1
4542 Xalpha_j, TRUE, FALSE,
4543 EL_CHAR('J'), -1, -1
4546 Xalpha_k, TRUE, FALSE,
4547 EL_CHAR('K'), -1, -1
4550 Xalpha_l, TRUE, FALSE,
4551 EL_CHAR('L'), -1, -1
4554 Xalpha_m, TRUE, FALSE,
4555 EL_CHAR('M'), -1, -1
4558 Xalpha_n, TRUE, FALSE,
4559 EL_CHAR('N'), -1, -1
4562 Xalpha_o, TRUE, FALSE,
4563 EL_CHAR('O'), -1, -1
4566 Xalpha_p, TRUE, FALSE,
4567 EL_CHAR('P'), -1, -1
4570 Xalpha_q, TRUE, FALSE,
4571 EL_CHAR('Q'), -1, -1
4574 Xalpha_r, TRUE, FALSE,
4575 EL_CHAR('R'), -1, -1
4578 Xalpha_s, TRUE, FALSE,
4579 EL_CHAR('S'), -1, -1
4582 Xalpha_t, TRUE, FALSE,
4583 EL_CHAR('T'), -1, -1
4586 Xalpha_u, TRUE, FALSE,
4587 EL_CHAR('U'), -1, -1
4590 Xalpha_v, TRUE, FALSE,
4591 EL_CHAR('V'), -1, -1
4594 Xalpha_w, TRUE, FALSE,
4595 EL_CHAR('W'), -1, -1
4598 Xalpha_x, TRUE, FALSE,
4599 EL_CHAR('X'), -1, -1
4602 Xalpha_y, TRUE, FALSE,
4603 EL_CHAR('Y'), -1, -1
4606 Xalpha_z, TRUE, FALSE,
4607 EL_CHAR('Z'), -1, -1
4610 Xalpha_arrow_e, TRUE, FALSE,
4611 EL_CHAR('>'), -1, -1
4614 Xalpha_arrow_w, TRUE, FALSE,
4615 EL_CHAR('<'), -1, -1
4618 Xalpha_copyr, TRUE, FALSE,
4619 EL_CHAR('©'), -1, -1
4622 Xalpha_copyr, TRUE, FALSE,
4623 EL_CHAR('©'), -1, -1
4627 Xboom_bug, FALSE, FALSE,
4628 EL_BUG, ACTION_EXPLODING, -1
4631 Xboom_bomb, FALSE, FALSE,
4632 EL_BOMB, ACTION_EXPLODING, -1
4635 Xboom_android, FALSE, FALSE,
4636 EL_EMC_ANDROID, ACTION_OTHER, -1
4639 Xboom_1, FALSE, FALSE,
4640 EL_DEFAULT, ACTION_EXPLODING, -1
4643 Xboom_2, FALSE, FALSE,
4644 EL_DEFAULT, ACTION_EXPLODING, -1
4647 Znormal, FALSE, FALSE,
4651 Zdynamite, FALSE, FALSE,
4655 Zplayer, FALSE, FALSE,
4659 ZBORDER, FALSE, FALSE,
4669 static struct Mapping_EM_to_RND_player
4678 em_player_mapping_list[] =
4682 EL_PLAYER_1, ACTION_MOVING, MV_BIT_UP,
4686 EL_PLAYER_1, ACTION_MOVING, MV_BIT_RIGHT,
4690 EL_PLAYER_1, ACTION_MOVING, MV_BIT_DOWN,
4694 EL_PLAYER_1, ACTION_MOVING, MV_BIT_LEFT,
4698 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_UP,
4702 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_RIGHT,
4706 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_DOWN,
4710 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_LEFT,
4714 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_UP,
4718 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_RIGHT,
4722 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_DOWN,
4726 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_LEFT,
4730 EL_PLAYER_2, ACTION_MOVING, MV_BIT_UP,
4734 EL_PLAYER_2, ACTION_MOVING, MV_BIT_RIGHT,
4738 EL_PLAYER_2, ACTION_MOVING, MV_BIT_DOWN,
4742 EL_PLAYER_2, ACTION_MOVING, MV_BIT_LEFT,
4746 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_UP,
4750 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_RIGHT,
4754 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_DOWN,
4758 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_LEFT,
4762 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_UP,
4766 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_RIGHT,
4770 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_DOWN,
4774 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_LEFT,
4778 EL_PLAYER_1, ACTION_DEFAULT, -1,
4782 EL_PLAYER_2, ACTION_DEFAULT, -1,
4791 int map_element_RND_to_EM(int element_rnd)
4793 static unsigned short mapping_RND_to_EM[NUM_FILE_ELEMENTS];
4794 static boolean mapping_initialized = FALSE;
4796 if (!mapping_initialized)
4800 /* return "Xalpha_quest" for all undefined elements in mapping array */
4801 for (i = 0; i < NUM_FILE_ELEMENTS; i++)
4802 mapping_RND_to_EM[i] = Xalpha_quest;
4804 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
4805 if (em_object_mapping_list[i].is_rnd_to_em_mapping)
4806 mapping_RND_to_EM[em_object_mapping_list[i].element_rnd] =
4807 em_object_mapping_list[i].element_em;
4809 mapping_initialized = TRUE;
4812 if (element_rnd >= 0 && element_rnd < NUM_FILE_ELEMENTS)
4813 return mapping_RND_to_EM[element_rnd];
4815 Error(ERR_WARN, "invalid RND level element %d", element_rnd);
4820 int map_element_EM_to_RND(int element_em)
4822 static unsigned short mapping_EM_to_RND[TILE_MAX];
4823 static boolean mapping_initialized = FALSE;
4825 if (!mapping_initialized)
4829 /* return "EL_UNKNOWN" for all undefined elements in mapping array */
4830 for (i = 0; i < TILE_MAX; i++)
4831 mapping_EM_to_RND[i] = EL_UNKNOWN;
4833 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
4834 mapping_EM_to_RND[em_object_mapping_list[i].element_em] =
4835 em_object_mapping_list[i].element_rnd;
4837 mapping_initialized = TRUE;
4840 if (element_em >= 0 && element_em < TILE_MAX)
4841 return mapping_EM_to_RND[element_em];
4843 Error(ERR_WARN, "invalid EM level element %d", element_em);
4850 int map_element_RND_to_EM(int element_rnd)
4852 static unsigned short mapping_RND_to_EM[NUM_FILE_ELEMENTS];
4853 static boolean mapping_initialized = FALSE;
4860 mapping_RND_to_EM_list[] =
4862 { Xblank, EL_EMPTY },
4863 { Xstone, EL_ROCK },
4865 { Xbug_n, EL_BUG_UP },
4866 { Xbug_e, EL_BUG_RIGHT },
4867 { Xbug_s, EL_BUG_DOWN },
4868 { Xbug_w, EL_BUG_LEFT },
4869 { Xtank_n, EL_SPACESHIP_UP },
4870 { Xtank_e, EL_SPACESHIP_RIGHT },
4871 { Xtank_s, EL_SPACESHIP_DOWN },
4872 { Xtank_w, EL_SPACESHIP_LEFT },
4873 { Xandroid, EL_EMC_ANDROID },
4874 { Xandroid_1_n, EL_EMC_ANDROID_UP },
4875 { Xandroid_1_e, EL_EMC_ANDROID_RIGHT },
4876 { Xandroid_1_w, EL_EMC_ANDROID_LEFT },
4877 { Xandroid_1_s, EL_EMC_ANDROID_DOWN },
4878 { Xspring, EL_SPRING },
4879 { Xeater_n, EL_YAMYAM },
4880 { Xalien, EL_ROBOT },
4881 { Xemerald, EL_EMERALD },
4882 { Xdiamond, EL_DIAMOND },
4883 { Xdrip_fall, EL_AMOEBA_DROP },
4885 { Xballoon, EL_BALLOON },
4886 { Xgrass, EL_EMC_GRASS },
4888 { Xacid_ne, EL_ACID_POOL_TOPRIGHT },
4889 { Xacid_se, EL_ACID_POOL_BOTTOMRIGHT },
4890 { Xacid_s, EL_ACID_POOL_BOTTOM },
4891 { Xacid_sw, EL_ACID_POOL_BOTTOMLEFT },
4892 { Xacid_nw, EL_ACID_POOL_TOPLEFT },
4893 { Xacid_1, EL_ACID },
4894 { Xball_1, EL_EMC_MAGIC_BALL },
4895 { Xgrow_ns, EL_EMC_GROW },
4896 { Xwonderwall, EL_MAGIC_WALL },
4897 { Xamoeba_1, EL_AMOEBA_WET },
4898 { Xdoor_1, EL_EM_GATE_1 },
4899 { Xdoor_2, EL_EM_GATE_2 },
4900 { Xdoor_3, EL_EM_GATE_3 },
4901 { Xdoor_4, EL_EM_GATE_4 },
4902 { Xdoor_5, EL_EMC_GATE_5 },
4903 { Xdoor_6, EL_EMC_GATE_6 },
4904 { Xdoor_7, EL_EMC_GATE_7 },
4905 { Xdoor_8, EL_EMC_GATE_8 },
4906 { Xkey_1, EL_EM_KEY_1 },
4907 { Xkey_2, EL_EM_KEY_2 },
4908 { Xkey_3, EL_EM_KEY_3 },
4909 { Xkey_4, EL_EM_KEY_4 },
4910 { Xkey_5, EL_EMC_KEY_5 },
4911 { Xkey_6, EL_EMC_KEY_6 },
4912 { Xkey_7, EL_EMC_KEY_7 },
4913 { Xkey_8, EL_EMC_KEY_8 },
4914 { Xwind_n, EL_BALLOON_SWITCH_UP },
4915 { Xwind_e, EL_BALLOON_SWITCH_RIGHT },
4916 { Xwind_s, EL_BALLOON_SWITCH_DOWN },
4917 { Xwind_w, EL_BALLOON_SWITCH_LEFT },
4918 { Xwind_nesw, EL_BALLOON_SWITCH_ANY },
4919 { Xwind_stop, EL_BALLOON_SWITCH_NONE },
4920 { Xexit, EL_EXIT_CLOSED },
4921 { Xexit_1, EL_EXIT_OPEN },
4922 { Xdynamite, EL_DYNAMITE },
4923 { Xdynamite_1, EL_DYNAMITE_ACTIVE },
4924 { Xbumper, EL_EMC_BUMPER },
4925 { Xwheel, EL_ROBOT_WHEEL },
4926 { Xswitch, EL_UNKNOWN },
4927 { Xsand, EL_QUICKSAND_EMPTY },
4928 { Xsand_stone, EL_QUICKSAND_FULL },
4929 { Xplant, EL_EMC_PLANT },
4930 { Xlenses, EL_EMC_LENSES },
4931 { Xmagnify, EL_EMC_MAGNIFIER },
4932 { Xdripper, EL_UNKNOWN },
4933 { Xfake_blank, EL_INVISIBLE_WALL },
4934 { Xfake_grass, EL_INVISIBLE_SAND },
4935 { Xfake_door_1, EL_EM_GATE_1_GRAY },
4936 { Xfake_door_2, EL_EM_GATE_2_GRAY },
4937 { Xfake_door_3, EL_EM_GATE_3_GRAY },
4938 { Xfake_door_4, EL_EM_GATE_4_GRAY },
4939 { Xfake_door_5, EL_EMC_GATE_5_GRAY },
4940 { Xfake_door_6, EL_EMC_GATE_6_GRAY },
4941 { Xfake_door_7, EL_EMC_GATE_7_GRAY },
4942 { Xfake_door_8, EL_EMC_GATE_8_GRAY },
4943 { Xsteel_1, EL_STEELWALL },
4944 { Xsteel_2, EL_UNKNOWN },
4945 { Xsteel_3, EL_EMC_STEELWALL_1 },
4946 { Xsteel_4, EL_UNKNOWN },
4947 { Xwall_1, EL_WALL },
4948 { Xwall_2, EL_UNKNOWN },
4949 { Xwall_3, EL_UNKNOWN },
4950 { Xwall_4, EL_UNKNOWN },
4951 { Xround_wall_1, EL_WALL_SLIPPERY },
4952 { Xround_wall_2, EL_UNKNOWN },
4953 { Xround_wall_3, EL_UNKNOWN },
4954 { Xround_wall_4, EL_UNKNOWN },
4955 { Xdecor_1, EL_UNKNOWN },
4956 { Xdecor_2, EL_EMC_WALL_6 },
4957 { Xdecor_3, EL_EMC_WALL_4 },
4958 { Xdecor_4, EL_EMC_WALL_5 },
4959 { Xdecor_5, EL_EMC_WALL_7 },
4960 { Xdecor_6, EL_EMC_WALL_8 },
4961 { Xdecor_7, EL_UNKNOWN },
4962 { Xdecor_8, EL_EMC_WALL_1 },
4963 { Xdecor_9, EL_EMC_WALL_2 },
4964 { Xdecor_10, EL_EMC_WALL_3 },
4965 { Xdecor_11, EL_UNKNOWN },
4966 { Xdecor_12, EL_UNKNOWN },
4967 { Xalpha_0, EL_CHAR('0') },
4968 { Xalpha_1, EL_CHAR('1') },
4969 { Xalpha_2, EL_CHAR('2') },
4970 { Xalpha_3, EL_CHAR('3') },
4971 { Xalpha_4, EL_CHAR('4') },
4972 { Xalpha_5, EL_CHAR('5') },
4973 { Xalpha_6, EL_CHAR('6') },
4974 { Xalpha_7, EL_CHAR('7') },
4975 { Xalpha_8, EL_CHAR('8') },
4976 { Xalpha_9, EL_CHAR('9') },
4977 { Xalpha_excla, EL_CHAR('!') },
4978 { Xalpha_quote, EL_CHAR('"') },
4979 { Xalpha_comma, EL_CHAR(',') },
4980 { Xalpha_minus, EL_CHAR('-') },
4981 { Xalpha_perio, EL_CHAR('.') },
4982 { Xalpha_colon, EL_CHAR(':') },
4983 { Xalpha_quest, EL_CHAR('?') },
4984 { Xalpha_a, EL_CHAR('A') },
4985 { Xalpha_b, EL_CHAR('B') },
4986 { Xalpha_c, EL_CHAR('C') },
4987 { Xalpha_d, EL_CHAR('D') },
4988 { Xalpha_e, EL_CHAR('E') },
4989 { Xalpha_f, EL_CHAR('F') },
4990 { Xalpha_g, EL_CHAR('G') },
4991 { Xalpha_h, EL_CHAR('H') },
4992 { Xalpha_i, EL_CHAR('I') },
4993 { Xalpha_j, EL_CHAR('J') },
4994 { Xalpha_k, EL_CHAR('K') },
4995 { Xalpha_l, EL_CHAR('L') },
4996 { Xalpha_m, EL_CHAR('M') },
4997 { Xalpha_n, EL_CHAR('N') },
4998 { Xalpha_o, EL_CHAR('O') },
4999 { Xalpha_p, EL_CHAR('P') },
5000 { Xalpha_q, EL_CHAR('Q') },
5001 { Xalpha_r, EL_CHAR('R') },
5002 { Xalpha_s, EL_CHAR('S') },
5003 { Xalpha_t, EL_CHAR('T') },
5004 { Xalpha_u, EL_CHAR('U') },
5005 { Xalpha_v, EL_CHAR('V') },
5006 { Xalpha_w, EL_CHAR('W') },
5007 { Xalpha_x, EL_CHAR('X') },
5008 { Xalpha_y, EL_CHAR('Y') },
5009 { Xalpha_z, EL_CHAR('Z') },
5010 { Xalpha_arrow_e, EL_CHAR('>') },
5011 { Xalpha_arrow_w, EL_CHAR('<') },
5012 { Xalpha_copyr, EL_CHAR('©') },
5014 { Zplayer, EL_PLAYER_1 },
5015 { Zplayer, EL_PLAYER_2 },
5016 { Zplayer, EL_PLAYER_3 },
5017 { Zplayer, EL_PLAYER_4 },
5019 { ZBORDER, EL_EMC_LEVEL_BORDER },
5024 if (!mapping_initialized)
5028 /* return "Xalpha_quest" for all undefined elements in mapping array */
5029 for (i = 0; i < NUM_FILE_ELEMENTS; i++)
5030 mapping_RND_to_EM[i] = Xalpha_quest;
5032 for (i = 0; mapping_RND_to_EM_list[i].element_rnd != -1; i++)
5033 mapping_RND_to_EM[mapping_RND_to_EM_list[i].element_rnd] =
5034 mapping_RND_to_EM_list[i].element_em;
5036 mapping_initialized = TRUE;
5039 if (element_rnd >= 0 && element_rnd < NUM_FILE_ELEMENTS)
5040 return mapping_RND_to_EM[element_rnd];
5042 Error(ERR_WARN, "invalid RND level element %d", element_rnd);
5047 int map_element_EM_to_RND(int element_em)
5049 static unsigned short mapping_EM_to_RND[TILE_MAX];
5050 static boolean mapping_initialized = FALSE;
5057 em_object_mapping_list[] =
5059 { Xblank, EL_EMPTY },
5060 { Yacid_splash_eB, EL_EMPTY },
5061 { Yacid_splash_wB, EL_EMPTY },
5063 #ifdef EM_ENGINE_BAD_ROLL
5064 { Xstone_force_e, EL_ROCK },
5065 { Xstone_force_w, EL_ROCK },
5066 { Xnut_force_e, EL_NUT },
5067 { Xnut_force_w, EL_NUT },
5068 { Xspring_force_e, EL_SPRING },
5069 { Xspring_force_w, EL_SPRING },
5070 { Xemerald_force_e, EL_EMERALD },
5071 { Xemerald_force_w, EL_EMERALD },
5072 { Xdiamond_force_e, EL_DIAMOND },
5073 { Xdiamond_force_w, EL_DIAMOND },
5074 { Xbomb_force_e, EL_BOMB },
5075 { Xbomb_force_w, EL_BOMB },
5078 { Xstone, EL_ROCK },
5079 { Xstone_pause, EL_ROCK },
5080 { Xstone_fall, EL_ROCK },
5081 { Ystone_s, EL_ROCK },
5082 { Ystone_sB, EL_ROCK },
5083 { Ystone_e, EL_ROCK },
5084 { Ystone_eB, EL_ROCK },
5085 { Ystone_w, EL_ROCK },
5086 { Ystone_wB, EL_ROCK },
5088 { Xnut_pause, EL_NUT },
5089 { Xnut_fall, EL_NUT },
5091 { Ynut_sB, EL_NUT },
5093 { Ynut_eB, EL_NUT },
5095 { Ynut_wB, EL_NUT },
5096 { Xbug_n, EL_BUG_UP },
5097 { Xbug_e, EL_BUG_RIGHT },
5098 { Xbug_s, EL_BUG_DOWN },
5099 { Xbug_w, EL_BUG_LEFT },
5100 { Xbug_gon, EL_BUG_UP },
5101 { Xbug_goe, EL_BUG_RIGHT },
5102 { Xbug_gos, EL_BUG_DOWN },
5103 { Xbug_gow, EL_BUG_LEFT },
5104 { Ybug_n, EL_BUG_UP },
5105 { Ybug_nB, EL_BUG_UP },
5106 { Ybug_e, EL_BUG_RIGHT },
5107 { Ybug_eB, EL_BUG_RIGHT },
5108 { Ybug_s, EL_BUG_DOWN },
5109 { Ybug_sB, EL_BUG_DOWN },
5110 { Ybug_w, EL_BUG_LEFT },
5111 { Ybug_wB, EL_BUG_LEFT },
5112 { Ybug_w_n, EL_BUG_UP },
5113 { Ybug_n_e, EL_BUG_RIGHT },
5114 { Ybug_e_s, EL_BUG_DOWN },
5115 { Ybug_s_w, EL_BUG_LEFT },
5116 { Ybug_e_n, EL_BUG_UP },
5117 { Ybug_s_e, EL_BUG_RIGHT },
5118 { Ybug_w_s, EL_BUG_DOWN },
5119 { Ybug_n_w, EL_BUG_LEFT },
5120 { Ybug_stone, EL_ROCK },
5121 { Ybug_spring, EL_SPRING },
5122 { Xtank_n, EL_SPACESHIP_UP },
5123 { Xtank_e, EL_SPACESHIP_RIGHT },
5124 { Xtank_s, EL_SPACESHIP_DOWN },
5125 { Xtank_w, EL_SPACESHIP_LEFT },
5126 { Xtank_gon, EL_SPACESHIP_UP },
5127 { Xtank_goe, EL_SPACESHIP_RIGHT },
5128 { Xtank_gos, EL_SPACESHIP_DOWN },
5129 { Xtank_gow, EL_SPACESHIP_LEFT },
5130 { Ytank_n, EL_SPACESHIP_UP },
5131 { Ytank_nB, EL_SPACESHIP_UP },
5132 { Ytank_e, EL_SPACESHIP_RIGHT },
5133 { Ytank_eB, EL_SPACESHIP_RIGHT },
5134 { Ytank_s, EL_SPACESHIP_DOWN },
5135 { Ytank_sB, EL_SPACESHIP_DOWN },
5136 { Ytank_w, EL_SPACESHIP_LEFT },
5137 { Ytank_wB, EL_SPACESHIP_LEFT },
5138 { Ytank_w_n, EL_SPACESHIP_UP },
5139 { Ytank_n_e, EL_SPACESHIP_RIGHT },
5140 { Ytank_e_s, EL_SPACESHIP_DOWN },
5141 { Ytank_s_w, EL_SPACESHIP_LEFT },
5142 { Ytank_e_n, EL_SPACESHIP_UP },
5143 { Ytank_s_e, EL_SPACESHIP_RIGHT },
5144 { Ytank_w_s, EL_SPACESHIP_DOWN },
5145 { Ytank_n_w, EL_SPACESHIP_LEFT },
5146 { Ytank_stone, EL_ROCK },
5147 { Ytank_spring, EL_SPRING },
5148 { Xandroid, EL_EMC_ANDROID },
5149 { Xandroid_1_n, EL_EMC_ANDROID_UP },
5150 { Xandroid_2_n, EL_EMC_ANDROID_UP },
5151 { Xandroid_1_e, EL_EMC_ANDROID_RIGHT },
5152 { Xandroid_2_e, EL_EMC_ANDROID_RIGHT },
5153 { Xandroid_1_w, EL_EMC_ANDROID_LEFT },
5154 { Xandroid_2_w, EL_EMC_ANDROID_LEFT },
5155 { Xandroid_1_s, EL_EMC_ANDROID_DOWN },
5156 { Xandroid_2_s, EL_EMC_ANDROID_DOWN },
5157 { Yandroid_n, EL_EMC_ANDROID_UP },
5158 { Yandroid_nB, EL_EMC_ANDROID_UP },
5159 { Yandroid_ne, EL_EMC_ANDROID_RIGHT_UP },
5160 { Yandroid_neB, EL_EMC_ANDROID_RIGHT_UP },
5161 { Yandroid_e, EL_EMC_ANDROID_RIGHT },
5162 { Yandroid_eB, EL_EMC_ANDROID_RIGHT },
5163 { Yandroid_se, EL_EMC_ANDROID_RIGHT_DOWN },
5164 { Yandroid_seB, EL_EMC_ANDROID_RIGHT_DOWN },
5165 { Yandroid_s, EL_EMC_ANDROID_DOWN },
5166 { Yandroid_sB, EL_EMC_ANDROID_DOWN },
5167 { Yandroid_sw, EL_EMC_ANDROID_LEFT_DOWN },
5168 { Yandroid_swB, EL_EMC_ANDROID_LEFT_DOWN },
5169 { Yandroid_w, EL_EMC_ANDROID_LEFT },
5170 { Yandroid_wB, EL_EMC_ANDROID_LEFT },
5171 { Yandroid_nw, EL_EMC_ANDROID_LEFT_UP },
5172 { Yandroid_nwB, EL_EMC_ANDROID_LEFT_UP },
5173 { Xspring, EL_SPRING },
5174 { Xspring_pause, EL_SPRING },
5175 { Xspring_e, EL_SPRING },
5176 { Xspring_w, EL_SPRING },
5177 { Xspring_fall, EL_SPRING },
5178 { Yspring_s, EL_SPRING },
5179 { Yspring_sB, EL_SPRING },
5180 { Yspring_e, EL_SPRING },
5181 { Yspring_eB, EL_SPRING },
5182 { Yspring_w, EL_SPRING },
5183 { Yspring_wB, EL_SPRING },
5184 { Yspring_kill_e, EL_SPRING },
5185 { Yspring_kill_eB, EL_SPRING },
5186 { Yspring_kill_w, EL_SPRING },
5187 { Yspring_kill_wB, EL_SPRING },
5188 { Xeater_n, EL_YAMYAM },
5189 { Xeater_e, EL_YAMYAM },
5190 { Xeater_w, EL_YAMYAM },
5191 { Xeater_s, EL_YAMYAM },
5192 { Yeater_n, EL_YAMYAM },
5193 { Yeater_nB, EL_YAMYAM },
5194 { Yeater_e, EL_YAMYAM },
5195 { Yeater_eB, EL_YAMYAM },
5196 { Yeater_s, EL_YAMYAM },
5197 { Yeater_sB, EL_YAMYAM },
5198 { Yeater_w, EL_YAMYAM },
5199 { Yeater_wB, EL_YAMYAM },
5200 { Yeater_stone, EL_ROCK },
5201 { Yeater_spring, EL_SPRING },
5202 { Xalien, EL_ROBOT },
5203 { Xalien_pause, EL_ROBOT },
5204 { Yalien_n, EL_ROBOT },
5205 { Yalien_nB, EL_ROBOT },
5206 { Yalien_e, EL_ROBOT },
5207 { Yalien_eB, EL_ROBOT },
5208 { Yalien_s, EL_ROBOT },
5209 { Yalien_sB, EL_ROBOT },
5210 { Yalien_w, EL_ROBOT },
5211 { Yalien_wB, EL_ROBOT },
5212 { Yalien_stone, EL_ROCK },
5213 { Yalien_spring, EL_SPRING },
5214 { Xemerald, EL_EMERALD },
5215 { Xemerald_pause, EL_EMERALD },
5216 { Xemerald_fall, EL_EMERALD },
5217 { Xemerald_shine, EL_EMERALD },
5218 { Yemerald_s, EL_EMERALD },
5219 { Yemerald_sB, EL_EMERALD },
5220 { Yemerald_e, EL_EMERALD },
5221 { Yemerald_eB, EL_EMERALD },
5222 { Yemerald_w, EL_EMERALD },
5223 { Yemerald_wB, EL_EMERALD },
5224 { Yemerald_eat, EL_EMERALD },
5225 { Yemerald_stone, EL_ROCK },
5226 { Xdiamond, EL_DIAMOND },
5227 { Xdiamond_pause, EL_DIAMOND },
5228 { Xdiamond_fall, EL_DIAMOND },
5229 { Xdiamond_shine, EL_DIAMOND },
5230 { Ydiamond_s, EL_DIAMOND },
5231 { Ydiamond_sB, EL_DIAMOND },
5232 { Ydiamond_e, EL_DIAMOND },
5233 { Ydiamond_eB, EL_DIAMOND },
5234 { Ydiamond_w, EL_DIAMOND },
5235 { Ydiamond_wB, EL_DIAMOND },
5236 { Ydiamond_eat, EL_DIAMOND },
5237 { Ydiamond_stone, EL_ROCK },
5238 { Xdrip_fall, EL_AMOEBA_DROP },
5239 { Xdrip_stretch, EL_AMOEBA_DROP },
5240 { Xdrip_stretchB, EL_AMOEBA_DROP },
5241 { Xdrip_eat, EL_AMOEBA_DROP },
5242 { Ydrip_s1, EL_AMOEBA_DROP },
5243 { Ydrip_s1B, EL_AMOEBA_DROP },
5244 { Ydrip_s2, EL_AMOEBA_DROP },
5245 { Ydrip_s2B, EL_AMOEBA_DROP },
5247 { Xbomb_pause, EL_BOMB },
5248 { Xbomb_fall, EL_BOMB },
5249 { Ybomb_s, EL_BOMB },
5250 { Ybomb_sB, EL_BOMB },
5251 { Ybomb_e, EL_BOMB },
5252 { Ybomb_eB, EL_BOMB },
5253 { Ybomb_w, EL_BOMB },
5254 { Ybomb_wB, EL_BOMB },
5255 { Ybomb_eat, EL_BOMB },
5256 { Xballoon, EL_BALLOON },
5257 { Yballoon_n, EL_BALLOON },
5258 { Yballoon_nB, EL_BALLOON },
5259 { Yballoon_e, EL_BALLOON },
5260 { Yballoon_eB, EL_BALLOON },
5261 { Yballoon_s, EL_BALLOON },
5262 { Yballoon_sB, EL_BALLOON },
5263 { Yballoon_w, EL_BALLOON },
5264 { Yballoon_wB, EL_BALLOON },
5265 { Xgrass, EL_SAND },
5266 { Ygrass_nB, EL_SAND },
5267 { Ygrass_eB, EL_SAND },
5268 { Ygrass_sB, EL_SAND },
5269 { Ygrass_wB, EL_SAND },
5271 { Ydirt_nB, EL_SAND },
5272 { Ydirt_eB, EL_SAND },
5273 { Ydirt_sB, EL_SAND },
5274 { Ydirt_wB, EL_SAND },
5275 { Xacid_ne, EL_ACID_POOL_TOPRIGHT },
5276 { Xacid_se, EL_ACID_POOL_BOTTOMRIGHT },
5277 { Xacid_s, EL_ACID_POOL_BOTTOM },
5278 { Xacid_sw, EL_ACID_POOL_BOTTOMLEFT },
5279 { Xacid_nw, EL_ACID_POOL_TOPLEFT },
5280 { Xacid_1, EL_ACID },
5281 { Xacid_2, EL_ACID },
5282 { Xacid_3, EL_ACID },
5283 { Xacid_4, EL_ACID },
5284 { Xacid_5, EL_ACID },
5285 { Xacid_6, EL_ACID },
5286 { Xacid_7, EL_ACID },
5287 { Xacid_8, EL_ACID },
5288 { Xball_1, EL_EMC_MAGIC_BALL },
5289 { Xball_1B, EL_EMC_MAGIC_BALL },
5290 { Xball_2, EL_EMC_MAGIC_BALL },
5291 { Xball_2B, EL_EMC_MAGIC_BALL },
5292 { Yball_eat, EL_EMC_MAGIC_BALL },
5293 { Xgrow_ns, EL_EMC_GROW },
5294 { Ygrow_ns_eat, EL_EMC_GROW },
5295 { Xgrow_ew, EL_EMC_GROW },
5296 { Ygrow_ew_eat, EL_EMC_GROW },
5297 { Xwonderwall, EL_MAGIC_WALL },
5298 { XwonderwallB, EL_MAGIC_WALL },
5299 { Xamoeba_1, EL_AMOEBA_WET },
5300 { Xamoeba_2, EL_AMOEBA_WET },
5301 { Xamoeba_3, EL_AMOEBA_WET },
5302 { Xamoeba_4, EL_AMOEBA_WET },
5303 { Xamoeba_5, EL_AMOEBA_WET },
5304 { Xamoeba_6, EL_AMOEBA_WET },
5305 { Xamoeba_7, EL_AMOEBA_WET },
5306 { Xamoeba_8, EL_AMOEBA_WET },
5307 { Xdoor_1, EL_EM_GATE_1 },
5308 { Xdoor_2, EL_EM_GATE_2 },
5309 { Xdoor_3, EL_EM_GATE_3 },
5310 { Xdoor_4, EL_EM_GATE_4 },
5311 { Xdoor_5, EL_EMC_GATE_5 },
5312 { Xdoor_6, EL_EMC_GATE_6 },
5313 { Xdoor_7, EL_EMC_GATE_7 },
5314 { Xdoor_8, EL_EMC_GATE_8 },
5315 { Xkey_1, EL_EM_KEY_1 },
5316 { Xkey_2, EL_EM_KEY_2 },
5317 { Xkey_3, EL_EM_KEY_3 },
5318 { Xkey_4, EL_EM_KEY_4 },
5319 { Xkey_5, EL_EMC_KEY_5 },
5320 { Xkey_6, EL_EMC_KEY_6 },
5321 { Xkey_7, EL_EMC_KEY_7 },
5322 { Xkey_8, EL_EMC_KEY_8 },
5323 { Xwind_n, EL_BALLOON_SWITCH_UP },
5324 { Xwind_e, EL_BALLOON_SWITCH_RIGHT },
5325 { Xwind_s, EL_BALLOON_SWITCH_DOWN },
5326 { Xwind_w, EL_BALLOON_SWITCH_LEFT },
5327 { Xwind_nesw, EL_BALLOON_SWITCH_ANY },
5328 { Xwind_stop, EL_BALLOON_SWITCH_NONE },
5329 { Xexit, EL_EXIT_CLOSED },
5330 { Xexit_1, EL_EXIT_OPEN },
5331 { Xexit_2, EL_EXIT_OPEN },
5332 { Xexit_3, EL_EXIT_OPEN },
5333 { Xdynamite, EL_DYNAMITE },
5334 { Ydynamite_eat, EL_DYNAMITE },
5335 { Xdynamite_1, EL_DYNAMITE_ACTIVE },
5336 { Xdynamite_2, EL_DYNAMITE_ACTIVE },
5337 { Xdynamite_3, EL_DYNAMITE_ACTIVE },
5338 { Xdynamite_4, EL_DYNAMITE_ACTIVE },
5339 { Xbumper, EL_EMC_BUMPER },
5340 { XbumperB, EL_EMC_BUMPER },
5341 { Xwheel, EL_ROBOT_WHEEL },
5342 { XwheelB, EL_ROBOT_WHEEL },
5343 { Xswitch, EL_UNKNOWN },
5344 { XswitchB, EL_UNKNOWN },
5345 { Xsand, EL_QUICKSAND_EMPTY },
5346 { Xsand_stone, EL_QUICKSAND_FULL },
5347 { Xsand_stonein_1, EL_QUICKSAND_FULL },
5348 { Xsand_stonein_2, EL_QUICKSAND_FULL },
5349 { Xsand_stonein_3, EL_QUICKSAND_FULL },
5350 { Xsand_stonein_4, EL_QUICKSAND_FULL },
5351 { Xsand_stonesand_1, EL_QUICKSAND_FULL },
5352 { Xsand_stonesand_2, EL_QUICKSAND_FULL },
5353 { Xsand_stonesand_3, EL_QUICKSAND_FULL },
5354 { Xsand_stonesand_4, EL_QUICKSAND_FULL },
5355 { Xsand_stoneout_1, EL_QUICKSAND_FULL },
5356 { Xsand_stoneout_2, EL_QUICKSAND_FULL },
5357 { Xsand_sandstone_1, EL_QUICKSAND_FULL },
5358 { Xsand_sandstone_2, EL_QUICKSAND_FULL },
5359 { Xsand_sandstone_3, EL_QUICKSAND_FULL },
5360 { Xsand_sandstone_4, EL_QUICKSAND_FULL },
5361 { Xplant, EL_EMC_PLANT },
5362 { Yplant, EL_EMC_PLANT },
5363 { Xlenses, EL_EMC_LENSES },
5364 { Xmagnify, EL_EMC_MAGNIFIER },
5365 { Xdripper, EL_UNKNOWN },
5366 { XdripperB, EL_UNKNOWN },
5367 { Xfake_blank, EL_INVISIBLE_WALL },
5368 { Xfake_blankB, EL_INVISIBLE_WALL },
5369 { Xfake_grass, EL_INVISIBLE_SAND },
5370 { Xfake_grassB, EL_INVISIBLE_SAND },
5371 { Xfake_door_1, EL_EM_GATE_1_GRAY },
5372 { Xfake_door_2, EL_EM_GATE_2_GRAY },
5373 { Xfake_door_3, EL_EM_GATE_3_GRAY },
5374 { Xfake_door_4, EL_EM_GATE_4_GRAY },
5375 { Xfake_door_5, EL_EMC_GATE_5_GRAY },
5376 { Xfake_door_6, EL_EMC_GATE_6_GRAY },
5377 { Xfake_door_7, EL_EMC_GATE_7_GRAY },
5378 { Xfake_door_8, EL_EMC_GATE_8_GRAY },
5379 { Xsteel_1, EL_STEELWALL },
5380 { Xsteel_2, EL_UNKNOWN },
5381 { Xsteel_3, EL_EMC_STEELWALL_1 },
5382 { Xsteel_4, EL_UNKNOWN },
5383 { Xwall_1, EL_WALL },
5384 { Xwall_2, EL_UNKNOWN },
5385 { Xwall_3, EL_UNKNOWN },
5386 { Xwall_4, EL_UNKNOWN },
5387 { Xround_wall_1, EL_WALL_SLIPPERY },
5388 { Xround_wall_2, EL_UNKNOWN },
5389 { Xround_wall_3, EL_UNKNOWN },
5390 { Xround_wall_4, EL_UNKNOWN },
5391 { Xdecor_1, EL_UNKNOWN },
5392 { Xdecor_2, EL_EMC_WALL_6 },
5393 { Xdecor_3, EL_EMC_WALL_4 },
5394 { Xdecor_4, EL_EMC_WALL_5 },
5395 { Xdecor_5, EL_EMC_WALL_7 },
5396 { Xdecor_6, EL_EMC_WALL_8 },
5397 { Xdecor_7, EL_UNKNOWN },
5398 { Xdecor_8, EL_EMC_WALL_1 },
5399 { Xdecor_9, EL_EMC_WALL_2 },
5400 { Xdecor_10, EL_EMC_WALL_3 },
5401 { Xdecor_11, EL_UNKNOWN },
5402 { Xdecor_12, EL_UNKNOWN },
5403 { Xalpha_0, EL_CHAR('0') },
5404 { Xalpha_1, EL_CHAR('1') },
5405 { Xalpha_2, EL_CHAR('2') },
5406 { Xalpha_3, EL_CHAR('3') },
5407 { Xalpha_4, EL_CHAR('4') },
5408 { Xalpha_5, EL_CHAR('5') },
5409 { Xalpha_6, EL_CHAR('6') },
5410 { Xalpha_7, EL_CHAR('7') },
5411 { Xalpha_8, EL_CHAR('8') },
5412 { Xalpha_9, EL_CHAR('9') },
5413 { Xalpha_excla, EL_CHAR('!') },
5414 { Xalpha_quote, EL_CHAR('"') },
5415 { Xalpha_comma, EL_CHAR(',') },
5416 { Xalpha_minus, EL_CHAR('-') },
5417 { Xalpha_perio, EL_CHAR('.') },
5418 { Xalpha_colon, EL_CHAR(':') },
5419 { Xalpha_quest, EL_CHAR('?') },
5420 { Xalpha_a, EL_CHAR('A') },
5421 { Xalpha_b, EL_CHAR('B') },
5422 { Xalpha_c, EL_CHAR('C') },
5423 { Xalpha_d, EL_CHAR('D') },
5424 { Xalpha_e, EL_CHAR('E') },
5425 { Xalpha_f, EL_CHAR('F') },
5426 { Xalpha_g, EL_CHAR('G') },
5427 { Xalpha_h, EL_CHAR('H') },
5428 { Xalpha_i, EL_CHAR('I') },
5429 { Xalpha_j, EL_CHAR('J') },
5430 { Xalpha_k, EL_CHAR('K') },
5431 { Xalpha_l, EL_CHAR('L') },
5432 { Xalpha_m, EL_CHAR('M') },
5433 { Xalpha_n, EL_CHAR('N') },
5434 { Xalpha_o, EL_CHAR('O') },
5435 { Xalpha_p, EL_CHAR('P') },
5436 { Xalpha_q, EL_CHAR('Q') },
5437 { Xalpha_r, EL_CHAR('R') },
5438 { Xalpha_s, EL_CHAR('S') },
5439 { Xalpha_t, EL_CHAR('T') },
5440 { Xalpha_u, EL_CHAR('U') },
5441 { Xalpha_v, EL_CHAR('V') },
5442 { Xalpha_w, EL_CHAR('W') },
5443 { Xalpha_x, EL_CHAR('X') },
5444 { Xalpha_y, EL_CHAR('Y') },
5445 { Xalpha_z, EL_CHAR('Z') },
5446 { Xalpha_arrow_e, EL_CHAR('>') },
5447 { Xalpha_arrow_w, EL_CHAR('<') },
5448 { Xalpha_copyr, EL_CHAR('©') },
5450 { Zplayer, EL_PLAYER_1 },
5452 { ZBORDER, EL_EMC_LEVEL_BORDER },
5457 if (!mapping_initialized)
5461 /* return "EL_UNKNOWN" for all undefined elements in mapping array */
5462 for (i = 0; i < TILE_MAX; i++)
5463 mapping_EM_to_RND[i] = EL_UNKNOWN;
5465 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
5466 mapping_EM_to_RND[em_object_mapping_list[i].element_em] =
5467 em_object_mapping_list[i].element_rnd;
5469 mapping_initialized = TRUE;
5472 if (element_em >= 0 && element_em < TILE_MAX)
5473 return mapping_EM_to_RND[element_em];
5475 Error(ERR_WARN, "invalid EM level element %d", element_em);
5482 int get_next_element(int element)
5486 case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL;
5487 case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY;
5488 case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL;
5489 case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_ACTIVE;
5490 case EL_BD_MAGIC_WALL_FILLING: return EL_BD_MAGIC_WALL_FULL;
5491 case EL_BD_MAGIC_WALL_EMPTYING: return EL_BD_MAGIC_WALL_ACTIVE;
5492 case EL_AMOEBA_DROPPING: return EL_AMOEBA_WET;
5494 default: return element;
5499 int el_act_dir2img(int element, int action, int direction)
5501 element = GFX_ELEMENT(element);
5503 if (direction == MV_NO_MOVING)
5504 return element_info[element].graphic[action];
5506 direction = MV_DIR_BIT(direction);
5508 return element_info[element].direction_graphic[action][direction];
5511 int el_act_dir2img(int element, int action, int direction)
5513 element = GFX_ELEMENT(element);
5514 direction = MV_DIR_BIT(direction); /* default: MV_NO_MOVING => MV_DOWN */
5516 /* direction_graphic[][] == graphic[] for undefined direction graphics */
5517 return element_info[element].direction_graphic[action][direction];
5522 static int el_act_dir2crm(int element, int action, int direction)
5524 element = GFX_ELEMENT(element);
5526 if (direction == MV_NO_MOVING)
5527 return element_info[element].crumbled[action];
5529 direction = MV_DIR_BIT(direction);
5531 return element_info[element].direction_crumbled[action][direction];
5534 static int el_act_dir2crm(int element, int action, int direction)
5536 element = GFX_ELEMENT(element);
5537 direction = MV_DIR_BIT(direction); /* default: MV_NO_MOVING => MV_DOWN */
5539 /* direction_graphic[][] == graphic[] for undefined direction graphics */
5540 return element_info[element].direction_crumbled[action][direction];
5544 int el_act2img(int element, int action)
5546 element = GFX_ELEMENT(element);
5548 return element_info[element].graphic[action];
5551 int el_act2crm(int element, int action)
5553 element = GFX_ELEMENT(element);
5555 return element_info[element].crumbled[action];
5558 int el_dir2img(int element, int direction)
5560 element = GFX_ELEMENT(element);
5562 return el_act_dir2img(element, ACTION_DEFAULT, direction);
5565 int el2baseimg(int element)
5567 return element_info[element].graphic[ACTION_DEFAULT];
5570 int el2img(int element)
5572 element = GFX_ELEMENT(element);
5574 return element_info[element].graphic[ACTION_DEFAULT];
5577 int el2edimg(int element)
5579 element = GFX_ELEMENT(element);
5581 return element_info[element].special_graphic[GFX_SPECIAL_ARG_EDITOR];
5584 int el2preimg(int element)
5586 element = GFX_ELEMENT(element);
5588 return element_info[element].special_graphic[GFX_SPECIAL_ARG_PREVIEW];
5591 int getGameFrameDelay_EM(int native_em_game_frame_delay)
5593 return (GameFrameDelay == GAME_FRAME_DELAY ? native_em_game_frame_delay :
5597 unsigned int InitRND(long seed)
5599 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
5600 return InitEngineRND_EM(seed);
5602 return InitEngineRND(seed);
5605 #define DEBUG_EM_GFX 0
5607 void InitGraphicInfo_EM(void)
5609 struct Mapping_EM_to_RND_object object_mapping[TILE_MAX];
5610 struct Mapping_EM_to_RND_player player_mapping[2][SPR_MAX];
5614 if (graphic_info_em_object[0][0].bitmap == NULL)
5616 /* EM graphics not yet initialized in em_open_all() */
5622 /* always start with reliable default values */
5623 for (i = 0; i < TILE_MAX; i++)
5625 object_mapping[i].element_rnd = EL_UNKNOWN;
5626 object_mapping[i].is_backside = FALSE;
5627 object_mapping[i].action = ACTION_DEFAULT;
5628 object_mapping[i].direction = MV_NO_MOVING;
5631 /* always start with reliable default values */
5632 for (p = 0; p < 2; p++)
5634 for (i = 0; i < SPR_MAX; i++)
5636 player_mapping[p][i].element_rnd = EL_UNKNOWN;
5637 player_mapping[p][i].action = ACTION_DEFAULT;
5638 player_mapping[p][i].direction = MV_NO_MOVING;
5642 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
5644 int e = em_object_mapping_list[i].element_em;
5646 object_mapping[e].element_rnd = em_object_mapping_list[i].element_rnd;
5647 object_mapping[e].is_backside = em_object_mapping_list[i].is_backside;
5649 if (em_object_mapping_list[i].action != -1)
5650 object_mapping[e].action = em_object_mapping_list[i].action;
5652 if (em_object_mapping_list[i].direction != -1)
5653 object_mapping[e].direction = (1 << em_object_mapping_list[i].direction);
5656 for (i = 0; em_player_mapping_list[i].action_em != -1; i++)
5658 int a = em_player_mapping_list[i].action_em;
5659 int p = em_player_mapping_list[i].player_nr;
5661 player_mapping[p][a].element_rnd = em_player_mapping_list[i].element_rnd;
5663 if (em_player_mapping_list[i].action != -1)
5664 player_mapping[p][a].action = em_player_mapping_list[i].action;
5666 if (em_player_mapping_list[i].direction != -1)
5667 player_mapping[p][a].direction =
5668 (1 << em_player_mapping_list[i].direction);
5671 for (i = 0; i < TILE_MAX; i++)
5673 int element = object_mapping[i].element_rnd;
5674 int action = object_mapping[i].action;
5675 int direction = object_mapping[i].direction;
5676 boolean is_backside = object_mapping[i].is_backside;
5677 boolean action_removing = (action == ACTION_DIGGING ||
5678 action == ACTION_SNAPPING ||
5679 action == ACTION_COLLECTING);
5680 boolean action_exploding = ((action == ACTION_EXPLODING ||
5681 action == ACTION_SMASHED_BY_ROCK ||
5682 action == ACTION_SMASHED_BY_SPRING) &&
5683 element != EL_DIAMOND);
5684 boolean action_active = (action == ACTION_ACTIVE);
5685 boolean action_other = (action == ACTION_OTHER);
5687 for (j = 0; j < 8; j++)
5689 int effective_element = (j > 5 && i == Yacid_splash_eB ? EL_EMPTY :
5690 j > 5 && i == Yacid_splash_wB ? EL_EMPTY :
5692 i == Xdrip_stretch ? element :
5693 i == Xdrip_stretchB ? element :
5694 i == Ydrip_s1 ? element :
5695 i == Ydrip_s1B ? element :
5696 i == Xball_1B ? element :
5697 i == Xball_2 ? element :
5698 i == Xball_2B ? element :
5699 i == Yball_eat ? element :
5700 i == Ykey_1_eat ? element :
5701 i == Ykey_2_eat ? element :
5702 i == Ykey_3_eat ? element :
5703 i == Ykey_4_eat ? element :
5704 i == Ykey_5_eat ? element :
5705 i == Ykey_6_eat ? element :
5706 i == Ykey_7_eat ? element :
5707 i == Ykey_8_eat ? element :
5708 i == Ylenses_eat ? element :
5709 i == Ymagnify_eat ? element :
5710 i == Ygrass_eat ? element :
5711 i == Ydirt_eat ? element :
5712 i == Yspring_kill_e ? EL_SPRING :
5713 i == Yspring_kill_w ? EL_SPRING :
5714 i == Yemerald_stone ? EL_EMERALD :
5715 i == Ydiamond_stone ? EL_ROCK :
5716 i == Xsand_stonein_4 ? EL_EMPTY :
5717 i == Xsand_stoneout_2 ? EL_ROCK :
5718 is_backside ? EL_EMPTY :
5719 action_removing ? EL_EMPTY :
5721 int effective_action = (j < 7 ? action :
5722 i == Xdrip_stretch ? action :
5723 i == Xdrip_stretchB ? action :
5724 i == Ydrip_s1 ? action :
5725 i == Ydrip_s1B ? action :
5726 i == Xball_1B ? action :
5727 i == Xball_2 ? action :
5728 i == Xball_2B ? action :
5729 i == Yball_eat ? action :
5730 i == Ykey_1_eat ? action :
5731 i == Ykey_2_eat ? action :
5732 i == Ykey_3_eat ? action :
5733 i == Ykey_4_eat ? action :
5734 i == Ykey_5_eat ? action :
5735 i == Ykey_6_eat ? action :
5736 i == Ykey_7_eat ? action :
5737 i == Ykey_8_eat ? action :
5738 i == Ylenses_eat ? action :
5739 i == Ymagnify_eat ? action :
5740 i == Ygrass_eat ? action :
5741 i == Ydirt_eat ? action :
5742 i == Xsand_stonein_1 ? action :
5743 i == Xsand_stonein_2 ? action :
5744 i == Xsand_stonein_3 ? action :
5745 i == Xsand_stonein_4 ? action :
5746 i == Xsand_stoneout_1 ? action :
5747 i == Xsand_stoneout_2 ? action :
5748 i == Xboom_android ? ACTION_EXPLODING :
5749 action_exploding ? ACTION_EXPLODING :
5750 action_active ? action :
5751 action_other ? action :
5753 int graphic = (el_act_dir2img(effective_element, effective_action,
5755 int crumbled = (el_act_dir2crm(effective_element, effective_action,
5757 int base_graphic = el_act2img(effective_element, ACTION_DEFAULT);
5758 int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT);
5759 boolean has_crumbled_graphics = (base_crumbled != base_graphic);
5760 struct GraphicInfo *g = &graphic_info[graphic];
5761 struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
5764 /* ensure to get symmetric 3-frame, 2-delay animations as used in EM */
5765 boolean special_animation = (action != ACTION_DEFAULT &&
5766 g->anim_frames == 3 &&
5767 g->anim_delay == 2 &&
5768 g->anim_mode & ANIM_LINEAR);
5769 int sync_frame = (i == Xdrip_stretch ? 7 :
5770 i == Xdrip_stretchB ? 7 :
5771 i == Ydrip_s2 ? j + 8 :
5772 i == Ydrip_s2B ? j + 8 :
5782 i == Xball_2B ? j + 8 :
5783 i == Yball_eat ? j + 1 :
5784 i == Ykey_1_eat ? j + 1 :
5785 i == Ykey_2_eat ? j + 1 :
5786 i == Ykey_3_eat ? j + 1 :
5787 i == Ykey_4_eat ? j + 1 :
5788 i == Ykey_5_eat ? j + 1 :
5789 i == Ykey_6_eat ? j + 1 :
5790 i == Ykey_7_eat ? j + 1 :
5791 i == Ykey_8_eat ? j + 1 :
5792 i == Ylenses_eat ? j + 1 :
5793 i == Ymagnify_eat ? j + 1 :
5794 i == Ygrass_eat ? j + 1 :
5795 i == Ydirt_eat ? j + 1 :
5796 i == Xamoeba_1 ? 0 :
5797 i == Xamoeba_2 ? 1 :
5798 i == Xamoeba_3 ? 2 :
5799 i == Xamoeba_4 ? 3 :
5800 i == Xamoeba_5 ? 0 :
5801 i == Xamoeba_6 ? 1 :
5802 i == Xamoeba_7 ? 2 :
5803 i == Xamoeba_8 ? 3 :
5804 i == Xexit_2 ? j + 8 :
5805 i == Xexit_3 ? j + 16 :
5806 i == Xdynamite_1 ? 0 :
5807 i == Xdynamite_2 ? 20 :
5808 i == Xdynamite_3 ? 40 :
5809 i == Xdynamite_4 ? 60 :
5810 i == Xsand_stonein_1 ? j + 1 :
5811 i == Xsand_stonein_2 ? j + 9 :
5812 i == Xsand_stonein_3 ? j + 17 :
5813 i == Xsand_stonein_4 ? j + 25 :
5814 i == Xsand_stoneout_1 && j == 0 ? 0 :
5815 i == Xsand_stoneout_1 && j == 1 ? 0 :
5816 i == Xsand_stoneout_1 && j == 2 ? 1 :
5817 i == Xsand_stoneout_1 && j == 3 ? 2 :
5818 i == Xsand_stoneout_1 && j == 4 ? 2 :
5819 i == Xsand_stoneout_1 && j == 5 ? 3 :
5820 i == Xsand_stoneout_1 && j == 6 ? 4 :
5821 i == Xsand_stoneout_1 && j == 7 ? 4 :
5822 i == Xsand_stoneout_2 && j == 0 ? 5 :
5823 i == Xsand_stoneout_2 && j == 1 ? 6 :
5824 i == Xsand_stoneout_2 && j == 2 ? 7 :
5825 i == Xsand_stoneout_2 && j == 3 ? 8 :
5826 i == Xsand_stoneout_2 && j == 4 ? 9 :
5827 i == Xsand_stoneout_2 && j == 5 ? 11 :
5828 i == Xsand_stoneout_2 && j == 6 ? 13 :
5829 i == Xsand_stoneout_2 && j == 7 ? 15 :
5830 i == Xboom_bug && j == 1 ? 2 :
5831 i == Xboom_bug && j == 2 ? 2 :
5832 i == Xboom_bug && j == 3 ? 4 :
5833 i == Xboom_bug && j == 4 ? 4 :
5834 i == Xboom_bug && j == 5 ? 2 :
5835 i == Xboom_bug && j == 6 ? 2 :
5836 i == Xboom_bug && j == 7 ? 0 :
5837 i == Xboom_bomb && j == 1 ? 2 :
5838 i == Xboom_bomb && j == 2 ? 2 :
5839 i == Xboom_bomb && j == 3 ? 4 :
5840 i == Xboom_bomb && j == 4 ? 4 :
5841 i == Xboom_bomb && j == 5 ? 2 :
5842 i == Xboom_bomb && j == 6 ? 2 :
5843 i == Xboom_bomb && j == 7 ? 0 :
5844 i == Xboom_android && j == 7 ? 6 :
5845 i == Xboom_1 && j == 1 ? 2 :
5846 i == Xboom_1 && j == 2 ? 2 :
5847 i == Xboom_1 && j == 3 ? 4 :
5848 i == Xboom_1 && j == 4 ? 4 :
5849 i == Xboom_1 && j == 5 ? 6 :
5850 i == Xboom_1 && j == 6 ? 6 :
5851 i == Xboom_1 && j == 7 ? 8 :
5852 i == Xboom_2 && j == 0 ? 8 :
5853 i == Xboom_2 && j == 1 ? 8 :
5854 i == Xboom_2 && j == 2 ? 10 :
5855 i == Xboom_2 && j == 3 ? 10 :
5856 i == Xboom_2 && j == 4 ? 10 :
5857 i == Xboom_2 && j == 5 ? 12 :
5858 i == Xboom_2 && j == 6 ? 12 :
5859 i == Xboom_2 && j == 7 ? 12 :
5860 special_animation && j == 4 ? 3 :
5861 effective_action != action ? 0 :
5865 Bitmap *debug_bitmap = g_em->bitmap;
5866 int debug_src_x = g_em->src_x;
5867 int debug_src_y = g_em->src_y;
5870 int frame = getAnimationFrame(g->anim_frames,
5873 g->anim_start_frame,
5876 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y,
5877 g->double_movement && is_backside);
5880 g_em->bitmap = src_bitmap;
5881 g_em->src_x = src_x;
5882 g_em->src_y = src_y;
5883 g_em->src_offset_x = 0;
5884 g_em->src_offset_y = 0;
5885 g_em->dst_offset_x = 0;
5886 g_em->dst_offset_y = 0;
5887 g_em->width = TILEX;
5888 g_em->height = TILEY;
5890 g_em->has_crumbled_graphics = FALSE;
5891 g_em->crumbled_bitmap = NULL;
5892 g_em->crumbled_src_x = 0;
5893 g_em->crumbled_src_y = 0;
5894 g_em->crumbled_border_size = 0;
5898 if (effective_element == EL_EMC_GRASS &&
5899 effective_action == ACTION_DIGGING)
5900 printf("::: %d\n", crumbled);
5904 if (has_crumbled_graphics && crumbled == IMG_EMPTY_SPACE)
5905 printf("::: empty crumbled: %d [%s], %d, %d\n",
5906 effective_element, element_info[effective_element].token_name,
5907 effective_action, direction);
5910 /* if element can be crumbled, but certain action graphics are just empty
5911 space (like snapping sand with the original R'n'D graphics), do not
5912 treat these empty space graphics as crumbled graphics in EMC engine */
5913 if (has_crumbled_graphics && crumbled != IMG_EMPTY_SPACE)
5915 getGraphicSource(crumbled, frame, &src_bitmap, &src_x, &src_y);
5917 g_em->has_crumbled_graphics = TRUE;
5918 g_em->crumbled_bitmap = src_bitmap;
5919 g_em->crumbled_src_x = src_x;
5920 g_em->crumbled_src_y = src_y;
5921 g_em->crumbled_border_size = graphic_info[crumbled].border_size;
5925 if (!g->double_movement && (effective_action == ACTION_FALLING ||
5926 effective_action == ACTION_MOVING ||
5927 effective_action == ACTION_PUSHING))
5930 (effective_action == ACTION_FALLING ? MV_DOWN : direction);
5931 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? 1 : 0);
5932 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? 1 : 0);
5933 int cx = ABS(dx) * TILEX / 8;
5934 int cy = ABS(dy) * TILEY / 8;
5936 if (is_backside) /* tile where movement starts */
5938 if (dx < 0 || dy < 0)
5940 g_em->src_offset_x = cx * (j + 1);
5941 g_em->src_offset_y = cy * (j + 1);
5945 g_em->dst_offset_x = cx * (j + 1);
5946 g_em->dst_offset_y = cy * (j + 1);
5949 g_em->width = TILEX - cx * (j + 1);
5950 g_em->height = TILEY - cy * (j + 1);
5952 else /* tile where movement ends */
5954 if (dx < 0 || dy < 0)
5956 g_em->dst_offset_x = cx * (7 - j);
5957 g_em->dst_offset_y = cy * (7 - j);
5961 g_em->src_offset_x = cx * (7 - j);
5962 g_em->src_offset_y = cy * (7 - j);
5965 g_em->width = TILEX - cx * (7 - j);
5966 g_em->height = TILEY - cy * (7 - j);
5971 /* create unique graphic identifier to decide if tile must be redrawn */
5972 /* bit 31 - 16 (16 bit): EM style element
5973 bit 15 - 12 ( 4 bit): EM style frame
5974 bit 11 - 6 ( 6 bit): graphic width
5975 bit 5 - 0 ( 6 bit): graphic height */
5976 g_em->unique_identifier =
5977 (i << 16) | (j << 12) | (g_em->width << 6) | g_em->height;
5980 if (g_em->bitmap != debug_bitmap ||
5981 g_em->src_x != debug_src_x ||
5982 g_em->src_y != debug_src_y ||
5983 g_em->src_offset_x != 0 ||
5984 g_em->src_offset_y != 0 ||
5985 g_em->dst_offset_x != 0 ||
5986 g_em->dst_offset_y != 0 ||
5987 g_em->width != TILEX ||
5988 g_em->height != TILEY)
5990 static int last_i = -1;
5998 printf("::: EMC GFX ERROR for element %d -> %d ('%s', '%s', %d)",
5999 i, element, element_info[element].token_name,
6000 element_action_info[effective_action].suffix, direction);
6002 if (element != effective_element)
6003 printf(" [%d ('%s')]",
6005 element_info[effective_element].token_name);
6009 if (g_em->bitmap != debug_bitmap)
6010 printf(" %d (%d): different bitmap! (0x%08x != 0x%08x)\n",
6011 j, is_backside, (int)(g_em->bitmap), (int)(debug_bitmap));
6013 if (g_em->src_x != debug_src_x ||
6014 g_em->src_y != debug_src_y)
6015 printf(" frame %d (%c): %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
6016 j, (is_backside ? 'B' : 'F'),
6017 g_em->src_x, g_em->src_y,
6018 g_em->src_x / 32, g_em->src_y / 32,
6019 debug_src_x, debug_src_y,
6020 debug_src_x / 32, debug_src_y / 32);
6022 if (g_em->src_offset_x != 0 ||
6023 g_em->src_offset_y != 0 ||
6024 g_em->dst_offset_x != 0 ||
6025 g_em->dst_offset_y != 0)
6026 printf(" %d (%d): offsets %d,%d and %d,%d should be all 0\n",
6028 g_em->src_offset_x, g_em->src_offset_y,
6029 g_em->dst_offset_x, g_em->dst_offset_y);
6031 if (g_em->width != TILEX ||
6032 g_em->height != TILEY)
6033 printf(" %d (%d): size %d,%d should be %d,%d\n",
6035 g_em->width, g_em->height, TILEX, TILEY);
6042 for (p = 0; p < 2; p++)
6044 for (i = 0; i < SPR_MAX; i++)
6046 int element = player_mapping[p][i].element_rnd;
6047 int action = player_mapping[p][i].action;
6048 int direction = player_mapping[p][i].direction;
6050 for (j = 0; j < 8; j++)
6052 int effective_element = element;
6053 int effective_action = action;
6054 int graphic = (direction == MV_NO_MOVING ?
6055 el_act2img(effective_element, effective_action) :
6056 el_act_dir2img(effective_element, effective_action,
6058 struct GraphicInfo *g = &graphic_info[graphic];
6059 struct GraphicInfo_EM *g_em = &graphic_info_em_player[p][i][7 - j];
6065 Bitmap *debug_bitmap = g_em->bitmap;
6066 int debug_src_x = g_em->src_x;
6067 int debug_src_y = g_em->src_y;
6070 int frame = getAnimationFrame(g->anim_frames,
6073 g->anim_start_frame,
6076 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x,&src_y, FALSE);
6079 g_em->bitmap = src_bitmap;
6080 g_em->src_x = src_x;
6081 g_em->src_y = src_y;
6082 g_em->src_offset_x = 0;
6083 g_em->src_offset_y = 0;
6084 g_em->dst_offset_x = 0;
6085 g_em->dst_offset_y = 0;
6086 g_em->width = TILEX;
6087 g_em->height = TILEY;
6091 if (g_em->bitmap != debug_bitmap ||
6092 g_em->src_x != debug_src_x ||
6093 g_em->src_y != debug_src_y)
6095 static int last_i = -1;
6103 printf("::: EMC GFX ERROR for p/a %d/%d -> %d ('%s', '%s', %d)",
6104 p, i, element, element_info[element].token_name,
6105 element_action_info[effective_action].suffix, direction);
6107 if (element != effective_element)
6108 printf(" [%d ('%s')]",
6110 element_info[effective_element].token_name);
6114 if (g_em->bitmap != debug_bitmap)
6115 printf(" %d: different bitmap! (0x%08x != 0x%08x)\n",
6116 j, (int)(g_em->bitmap), (int)(debug_bitmap));
6118 if (g_em->src_x != debug_src_x ||
6119 g_em->src_y != debug_src_y)
6120 printf(" frame %d: %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
6122 g_em->src_x, g_em->src_y,
6123 g_em->src_x / 32, g_em->src_y / 32,
6124 debug_src_x, debug_src_y,
6125 debug_src_x / 32, debug_src_y / 32);