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(" Count: %d\n", Count[x][y]);
89 printf(" GfxElement: %d\n", GfxElement[x][y]);
90 printf(" GfxAction: %d\n", GfxAction[x][y]);
91 printf(" GfxFrame: %d\n", GfxFrame[x][y]);
95 void SetDrawtoField(int mode)
97 if (mode == DRAW_BUFFERED && setup.soft_scrolling)
108 drawto_field = fieldbuffer;
110 else /* DRAW_DIRECT, DRAW_BACKBUFFER */
116 BX2 = SCR_FIELDX - 1;
117 BY2 = SCR_FIELDY - 1;
121 drawto_field = (mode == DRAW_DIRECT ? window : backbuffer);
125 void RedrawPlayfield(boolean force_redraw, int x, int y, int width, int height)
127 if (game_status == GAME_MODE_PLAYING &&
128 level.game_engine_type == GAME_ENGINE_TYPE_EM)
130 BlitScreenToBitmap_EM(backbuffer);
132 else if (game_status == GAME_MODE_PLAYING && !game.envelope_active)
138 width = gfx.sxsize + 2 * TILEX;
139 height = gfx.sysize + 2 * TILEY;
142 if (force_redraw || setup.direct_draw)
145 int x1 = (x - SX) / TILEX, y1 = (y - SY) / TILEY;
146 int x2 = (x - SX + width) / TILEX, y2 = (y - SY + height) / TILEY;
148 if (setup.direct_draw)
149 SetDrawtoField(DRAW_BACKBUFFER);
151 for (xx = BX1; xx <= BX2; xx++)
152 for (yy = BY1; yy <= BY2; yy++)
153 if (xx >= x1 && xx <= x2 && yy >= y1 && yy <= y2)
154 DrawScreenField(xx, yy);
157 if (setup.direct_draw)
158 SetDrawtoField(DRAW_DIRECT);
161 if (setup.soft_scrolling)
163 int fx = FX, fy = FY;
165 fx += (ScreenMovDir & (MV_LEFT|MV_RIGHT) ? ScreenGfxPos : 0);
166 fy += (ScreenMovDir & (MV_UP|MV_DOWN) ? ScreenGfxPos : 0);
168 BlitBitmap(fieldbuffer, backbuffer, fx,fy, SXSIZE,SYSIZE, SX,SY);
172 BlitBitmap(drawto, window, x, y, width, height, x, y);
178 DrawBuffer *buffer = (drawto_field == window ? backbuffer : drawto_field);
180 if (setup.direct_draw && game_status == GAME_MODE_PLAYING)
181 redraw_mask &= ~REDRAW_MAIN;
183 if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD)
184 redraw_mask |= REDRAW_FIELD;
186 if (redraw_mask & REDRAW_FIELD)
187 redraw_mask &= ~REDRAW_TILES;
189 if (redraw_mask == REDRAW_NONE)
192 if (global.fps_slowdown && game_status == GAME_MODE_PLAYING)
194 static boolean last_frame_skipped = FALSE;
195 boolean skip_even_when_not_scrolling = TRUE;
196 boolean just_scrolling = (ScreenMovDir != 0);
197 boolean verbose = FALSE;
199 if (global.fps_slowdown_factor > 1 &&
200 (FrameCounter % global.fps_slowdown_factor) &&
201 (just_scrolling || skip_even_when_not_scrolling))
203 redraw_mask &= ~REDRAW_MAIN;
205 last_frame_skipped = TRUE;
208 printf("FRAME SKIPPED\n");
212 if (last_frame_skipped)
213 redraw_mask |= REDRAW_FIELD;
215 last_frame_skipped = FALSE;
218 printf("frame not skipped\n");
222 /* synchronize X11 graphics at this point; if we would synchronize the
223 display immediately after the buffer switching (after the XFlush),
224 this could mean that we have to wait for the graphics to complete,
225 although we could go on doing calculations for the next frame */
229 if (redraw_mask & REDRAW_ALL)
231 BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
235 if (redraw_mask & REDRAW_FIELD)
237 if (game_status != GAME_MODE_PLAYING ||
238 redraw_mask & REDRAW_FROM_BACKBUFFER)
240 BlitBitmap(backbuffer, window,
241 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE, REAL_SX, REAL_SY);
245 int fx = FX, fy = FY;
247 if (setup.soft_scrolling)
249 fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
250 fy += (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
253 if (setup.soft_scrolling ||
254 ABS(ScreenMovPos) + ScrollStepSize == TILEX ||
255 ABS(ScreenMovPos) == ScrollStepSize ||
256 redraw_tiles > REDRAWTILES_THRESHOLD)
258 BlitBitmap(buffer, window, fx, fy, SXSIZE, SYSIZE, SX, SY);
262 printf("redrawing all (ScreenGfxPos == %d) because %s\n",
264 (setup.soft_scrolling ?
265 "setup.soft_scrolling" :
266 ABS(ScreenGfxPos) + ScrollStepSize == TILEX ?
267 "ABS(ScreenGfxPos) + ScrollStepSize == TILEX" :
268 ABS(ScreenGfxPos) == ScrollStepSize ?
269 "ABS(ScreenGfxPos) == ScrollStepSize" :
270 "redraw_tiles > REDRAWTILES_THRESHOLD"));
276 redraw_mask &= ~REDRAW_MAIN;
279 if (redraw_mask & REDRAW_DOORS)
281 if (redraw_mask & REDRAW_DOOR_1)
282 BlitBitmap(backbuffer, window, DX, DY, DXSIZE, DYSIZE, DX, DY);
284 if (redraw_mask & REDRAW_DOOR_2)
285 BlitBitmap(backbuffer, window, VX, VY, VXSIZE, VYSIZE, VX, VY);
287 if (redraw_mask & REDRAW_DOOR_3)
288 BlitBitmap(backbuffer, window, EX, EY, EXSIZE, EYSIZE, EX, EY);
290 redraw_mask &= ~REDRAW_DOORS;
293 if (redraw_mask & REDRAW_MICROLEVEL)
295 BlitBitmap(backbuffer, window, SX, SY + 10 * TILEY, SXSIZE, 7 * TILEY,
296 SX, SY + 10 * TILEY);
298 redraw_mask &= ~REDRAW_MICROLEVEL;
301 if (redraw_mask & REDRAW_TILES)
303 for (x = 0; x < SCR_FIELDX; x++)
304 for (y = 0 ; y < SCR_FIELDY; y++)
305 if (redraw[redraw_x1 + x][redraw_y1 + y])
306 BlitBitmap(buffer, window,
307 FX + x * TILEX, FY + y * TILEY, TILEX, TILEY,
308 SX + x * TILEX, SY + y * TILEY);
311 if (redraw_mask & REDRAW_FPS) /* display frames per second */
316 sprintf(info1, " (only every %d. frame)", global.fps_slowdown_factor);
317 if (!global.fps_slowdown)
320 sprintf(text, "%.1f fps%s", global.frames_per_second, info1);
321 DrawTextExt(window, SX, SY, text, FONT_TEXT_2, BLIT_OPAQUE);
326 for (x = 0; x < MAX_BUF_XSIZE; x++)
327 for (y = 0; y < MAX_BUF_YSIZE; y++)
330 redraw_mask = REDRAW_NONE;
336 long fading_delay = 300;
338 if (setup.fading && (redraw_mask & REDRAW_FIELD))
345 ClearRectangle(window, REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
348 for (i = 0; i < 2 * FULL_SYSIZE; i++)
350 for (y = 0; y < FULL_SYSIZE; y++)
352 BlitBitmap(backbuffer, window,
353 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
361 for (i = 1; i < FULL_SYSIZE; i+=2)
362 BlitBitmap(backbuffer, window,
363 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
369 SetClipOrigin(clip_gc[PIX_FADEMASK], 0, 0);
370 BlitBitmapMasked(backbuffer, window,
371 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
376 SetClipOrigin(clip_gc[PIX_FADEMASK], -1, -1);
377 BlitBitmapMasked(backbuffer, window,
378 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
383 SetClipOrigin(clip_gc[PIX_FADEMASK], 0, -1);
384 BlitBitmapMasked(backbuffer, window,
385 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
390 SetClipOrigin(clip_gc[PIX_FADEMASK], -1, 0);
391 BlitBitmapMasked(backbuffer, window,
392 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
397 redraw_mask &= ~REDRAW_MAIN;
404 void SetMainBackgroundImageIfDefined(int graphic)
406 if (graphic_info[graphic].bitmap)
407 SetMainBackgroundImage(graphic);
410 void SetMainBackgroundImage(int graphic)
412 SetMainBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
413 graphic_info[graphic].bitmap ?
414 graphic_info[graphic].bitmap :
415 graphic_info[IMG_BACKGROUND].bitmap);
418 void SetDoorBackgroundImage(int graphic)
420 SetDoorBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
421 graphic_info[graphic].bitmap ?
422 graphic_info[graphic].bitmap :
423 graphic_info[IMG_BACKGROUND].bitmap);
426 void DrawBackground(int dst_x, int dst_y, int width, int height)
428 ClearRectangleOnBackground(backbuffer, dst_x, dst_y, width, height);
430 redraw_mask |= REDRAW_FIELD;
435 DrawBackground(REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
437 if (setup.soft_scrolling && game_status == GAME_MODE_PLAYING)
439 ClearRectangle(fieldbuffer, 0, 0, FXSIZE, FYSIZE);
440 SetDrawtoField(DRAW_BUFFERED);
443 SetDrawtoField(DRAW_BACKBUFFER);
445 if (setup.direct_draw && game_status == GAME_MODE_PLAYING)
447 ClearRectangle(window, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
448 SetDrawtoField(DRAW_DIRECT);
452 void MarkTileDirty(int x, int y)
454 int xx = redraw_x1 + x;
455 int yy = redraw_y1 + y;
460 redraw[xx][yy] = TRUE;
461 redraw_mask |= REDRAW_TILES;
464 void SetBorderElement()
468 BorderElement = EL_EMPTY;
470 for (y = 0; y < lev_fieldy && BorderElement == EL_EMPTY; y++)
472 for (x = 0; x < lev_fieldx; x++)
474 if (!IS_INDESTRUCTIBLE(Feld[x][y]))
475 BorderElement = EL_STEELWALL;
477 if (y != 0 && y != lev_fieldy - 1 && x != lev_fieldx - 1)
483 void SetRandomAnimationValue(int x, int y)
485 gfx.anim_random_frame = GfxRandom[x][y];
488 inline int getGraphicAnimationFrame(int graphic, int sync_frame)
490 /* animation synchronized with global frame counter, not move position */
491 if (graphic_info[graphic].anim_global_sync || sync_frame < 0)
492 sync_frame = FrameCounter;
494 return getAnimationFrame(graphic_info[graphic].anim_frames,
495 graphic_info[graphic].anim_delay,
496 graphic_info[graphic].anim_mode,
497 graphic_info[graphic].anim_start_frame,
501 inline void getGraphicSourceExt(int graphic, int frame, Bitmap **bitmap,
502 int *x, int *y, boolean get_backside)
504 struct GraphicInfo *g = &graphic_info[graphic];
505 int src_x = g->src_x + (get_backside ? g->offset2_x : 0);
506 int src_y = g->src_y + (get_backside ? g->offset2_y : 0);
510 if (g->offset_y == 0) /* frames are ordered horizontally */
512 int max_width = g->anim_frames_per_line * g->width;
513 int pos = (src_y / g->height) * max_width + src_x + frame * g->offset_x;
515 *x = pos % max_width;
516 *y = src_y % g->height + pos / max_width * g->height;
518 else if (g->offset_x == 0) /* frames are ordered vertically */
520 int max_height = g->anim_frames_per_line * g->height;
521 int pos = (src_x / g->width) * max_height + src_y + frame * g->offset_y;
523 *x = src_x % g->width + pos / max_height * g->width;
524 *y = pos % max_height;
526 else /* frames are ordered diagonally */
528 *x = src_x + frame * g->offset_x;
529 *y = src_y + frame * g->offset_y;
533 void getGraphicSource(int graphic, int frame, Bitmap **bitmap, int *x, int *y)
535 getGraphicSourceExt(graphic, frame, bitmap, x, y, FALSE);
538 void DrawGraphic(int x, int y, int graphic, int frame)
541 if (!IN_SCR_FIELD(x, y))
543 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
544 printf("DrawGraphic(): This should never happen!\n");
549 DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic, frame);
553 void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
559 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
560 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
563 void DrawGraphicThruMask(int x, int y, int graphic, int frame)
566 if (!IN_SCR_FIELD(x, y))
568 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
569 printf("DrawGraphicThruMask(): This should never happen!\n");
574 DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY, graphic,
579 void DrawGraphicThruMaskExt(DrawBuffer *d, int dst_x, int dst_y, int graphic,
585 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
587 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
588 dst_x - src_x, dst_y - src_y);
589 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dst_x, dst_y);
592 void DrawMiniGraphic(int x, int y, int graphic)
594 DrawMiniGraphicExt(drawto, SX + x * MINI_TILEX,SY + y * MINI_TILEY, graphic);
595 MarkTileDirty(x / 2, y / 2);
598 void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
600 struct GraphicInfo *g = &graphic_info[graphic];
602 int mini_starty = g->bitmap->height * 2 / 3;
605 *x = mini_startx + g->src_x / 2;
606 *y = mini_starty + g->src_y / 2;
609 void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
614 getMiniGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
615 BlitBitmap(src_bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
618 inline static void DrawGraphicShiftedNormal(int x, int y, int dx, int dy,
619 int graphic, int frame,
620 int cut_mode, int mask_mode)
625 int width = TILEX, height = TILEY;
628 if (dx || dy) /* shifted graphic */
630 if (x < BX1) /* object enters playfield from the left */
637 else if (x > BX2) /* object enters playfield from the right */
643 else if (x==BX1 && dx < 0) /* object leaves playfield to the left */
649 else if (x==BX2 && dx > 0) /* object leaves playfield to the right */
651 else if (dx) /* general horizontal movement */
652 MarkTileDirty(x + SIGN(dx), y);
654 if (y < BY1) /* object enters playfield from the top */
656 if (cut_mode==CUT_BELOW) /* object completely above top border */
664 else if (y > BY2) /* object enters playfield from the bottom */
670 else if (y==BY1 && dy < 0) /* object leaves playfield to the top */
676 else if (dy > 0 && cut_mode == CUT_ABOVE)
678 if (y == BY2) /* object completely above bottom border */
684 MarkTileDirty(x, y + 1);
685 } /* object leaves playfield to the bottom */
686 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
688 else if (dy) /* general vertical movement */
689 MarkTileDirty(x, y + SIGN(dy));
693 if (!IN_SCR_FIELD(x, y))
695 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
696 printf("DrawGraphicShifted(): This should never happen!\n");
701 if (width > 0 && height > 0)
703 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
708 dst_x = FX + x * TILEX + dx;
709 dst_y = FY + y * TILEY + dy;
711 if (mask_mode == USE_MASKING)
713 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
714 dst_x - src_x, dst_y - src_y);
715 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
719 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
726 inline static void DrawGraphicShiftedDouble(int x, int y, int dx, int dy,
727 int graphic, int frame,
728 int cut_mode, int mask_mode)
733 int width = TILEX, height = TILEY;
736 int x2 = x + SIGN(dx);
737 int y2 = y + SIGN(dy);
738 int anim_frames = graphic_info[graphic].anim_frames;
739 int sync_frame = (dx ? ABS(dx) : ABS(dy)) * anim_frames / TILESIZE;
741 /* re-calculate animation frame for two-tile movement animation */
742 frame = getGraphicAnimationFrame(graphic, sync_frame);
744 if (IN_SCR_FIELD(x1, y1)) /* movement start graphic inside screen area */
746 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, TRUE);
748 dst_x = FX + x1 * TILEX;
749 dst_y = FY + y1 * TILEY;
751 if (mask_mode == USE_MASKING)
753 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
754 dst_x - src_x, dst_y - src_y);
755 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
759 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
762 MarkTileDirty(x1, y1);
765 if (IN_SCR_FIELD(x2, y2)) /* movement end graphic inside screen area */
767 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, FALSE);
769 dst_x = FX + x2 * TILEX;
770 dst_y = FY + y2 * TILEY;
772 if (mask_mode == USE_MASKING)
774 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
775 dst_x - src_x, dst_y - src_y);
776 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
780 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
783 MarkTileDirty(x2, y2);
787 static void DrawGraphicShifted(int x, int y, int dx, int dy,
788 int graphic, int frame,
789 int cut_mode, int mask_mode)
793 DrawGraphic(x, y, graphic, frame);
798 if (graphic_info[graphic].double_movement) /* EM style movement images */
799 DrawGraphicShiftedDouble(x, y, dx, dy, graphic, frame, cut_mode,mask_mode);
801 DrawGraphicShiftedNormal(x, y, dx, dy, graphic, frame, cut_mode,mask_mode);
804 void DrawGraphicShiftedThruMask(int x, int y, int dx, int dy, int graphic,
805 int frame, int cut_mode)
807 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, USE_MASKING);
810 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
811 int cut_mode, int mask_mode)
813 int lx = LEVELX(x), ly = LEVELY(y);
817 if (IN_LEV_FIELD(lx, ly))
819 SetRandomAnimationValue(lx, ly);
821 graphic = el_act_dir2img(element, GfxAction[lx][ly], GfxDir[lx][ly]);
822 frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
824 /* do not use double (EM style) movement graphic when not moving */
825 if (graphic_info[graphic].double_movement && !dx && !dy)
827 graphic = el_act_dir2img(element, ACTION_DEFAULT, GfxDir[lx][ly]);
828 frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
831 else /* border element */
833 graphic = el2img(element);
834 frame = getGraphicAnimationFrame(graphic, -1);
837 if (element == EL_EXPANDABLE_WALL)
839 boolean left_stopped = FALSE, right_stopped = FALSE;
841 if (!IN_LEV_FIELD(lx - 1, ly) || IS_WALL(Feld[lx - 1][ly]))
843 if (!IN_LEV_FIELD(lx + 1, ly) || IS_WALL(Feld[lx + 1][ly]))
844 right_stopped = TRUE;
846 if (left_stopped && right_stopped)
848 else if (left_stopped)
850 graphic = IMG_EXPANDABLE_WALL_GROWING_RIGHT;
851 frame = graphic_info[graphic].anim_frames - 1;
853 else if (right_stopped)
855 graphic = IMG_EXPANDABLE_WALL_GROWING_LEFT;
856 frame = graphic_info[graphic].anim_frames - 1;
861 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
862 else if (mask_mode == USE_MASKING)
863 DrawGraphicThruMask(x, y, graphic, frame);
865 DrawGraphic(x, y, graphic, frame);
868 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
869 int cut_mode, int mask_mode)
871 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
872 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
873 cut_mode, mask_mode);
876 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
879 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
882 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
885 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
888 void DrawLevelElementThruMask(int x, int y, int element)
890 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
893 void DrawLevelFieldThruMask(int x, int y)
895 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
898 #define TILE_GFX_ELEMENT(x, y) \
899 (GfxElement[x][y] != EL_UNDEFINED && Feld[x][y] != EL_EXPLOSION ? \
900 GfxElement[x][y] : Feld[x][y])
902 static void DrawLevelFieldCrumbledSandExt(int x, int y, int graphic, int frame)
906 int sx = SCREENX(x), sy = SCREENY(y);
908 int width, height, cx, cy, i;
909 int crumbled_border_size = graphic_info[graphic].border_size;
910 static int xy[4][2] =
918 if (!IN_LEV_FIELD(x, y))
921 element = TILE_GFX_ELEMENT(x, y);
923 /* crumble field itself */
924 if (GFX_CRUMBLED(element) && !IS_MOVING(x, y))
926 if (!IN_SCR_FIELD(sx, sy))
929 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
931 for (i = 0; i < 4; i++)
933 int xx = x + xy[i][0];
934 int yy = y + xy[i][1];
936 element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
939 /* check if neighbour field is of same type */
940 if (GFX_CRUMBLED(element) && !IS_MOVING(xx, yy))
943 if (i == 1 || i == 2)
945 width = crumbled_border_size;
947 cx = (i == 2 ? TILEX - crumbled_border_size : 0);
953 height = crumbled_border_size;
955 cy = (i == 3 ? TILEY - crumbled_border_size : 0);
958 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
959 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
962 MarkTileDirty(sx, sy);
964 else /* crumble neighbour fields */
966 for (i = 0; i < 4; i++)
968 int xx = x + xy[i][0];
969 int yy = y + xy[i][1];
970 int sxx = sx + xy[i][0];
971 int syy = sy + xy[i][1];
974 if (!IN_LEV_FIELD(xx, yy) ||
975 !IN_SCR_FIELD(sxx, syy) ||
979 element = TILE_GFX_ELEMENT(xx, yy);
981 if (!GFX_CRUMBLED(element))
984 if (!IN_LEV_FIELD(xx, yy) ||
985 !IN_SCR_FIELD(sxx, syy) ||
986 !GFX_CRUMBLED(Feld[xx][yy]) ||
991 graphic = el_act2crm(Feld[xx][yy], ACTION_DEFAULT);
992 crumbled_border_size = graphic_info[graphic].border_size;
994 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
996 if (i == 1 || i == 2)
998 width = crumbled_border_size;
1000 cx = (i == 1 ? TILEX - crumbled_border_size : 0);
1006 height = crumbled_border_size;
1008 cy = (i == 0 ? TILEY - crumbled_border_size : 0);
1011 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1012 width, height, FX + sxx * TILEX + cx, FY + syy * TILEY + cy);
1014 MarkTileDirty(sxx, syy);
1019 void DrawLevelFieldCrumbledSand(int x, int y)
1023 if (!IN_LEV_FIELD(x, y))
1026 graphic = el_act2crm(Feld[x][y], ACTION_DEFAULT);
1028 DrawLevelFieldCrumbledSandExt(x, y, graphic, 0);
1031 void DrawLevelFieldCrumbledSandDigging(int x, int y, int direction,
1034 int graphic1 = el_act_dir2img(GfxElement[x][y], ACTION_DIGGING, direction);
1035 int graphic2 = el_act_dir2crm(GfxElement[x][y], ACTION_DIGGING, direction);
1036 int frame1 = getGraphicAnimationFrame(graphic1, step_frame);
1037 int frame2 = getGraphicAnimationFrame(graphic2, step_frame);
1038 int sx = SCREENX(x), sy = SCREENY(y);
1040 DrawGraphic(sx, sy, graphic1, frame1);
1041 DrawLevelFieldCrumbledSandExt(x, y, graphic2, frame2);
1044 void DrawLevelFieldCrumbledSandNeighbours(int x, int y)
1046 int sx = SCREENX(x), sy = SCREENY(y);
1047 static int xy[4][2] =
1056 for (i = 0; i < 4; i++)
1058 int xx = x + xy[i][0];
1059 int yy = y + xy[i][1];
1060 int sxx = sx + xy[i][0];
1061 int syy = sy + xy[i][1];
1063 if (!IN_LEV_FIELD(xx, yy) ||
1064 !IN_SCR_FIELD(sxx, syy) ||
1065 !GFX_CRUMBLED(Feld[xx][yy]) ||
1069 DrawLevelField(xx, yy);
1073 static int getBorderElement(int x, int y)
1077 { EL_STEELWALL_TOPLEFT, EL_INVISIBLE_STEELWALL_TOPLEFT },
1078 { EL_STEELWALL_TOPRIGHT, EL_INVISIBLE_STEELWALL_TOPRIGHT },
1079 { EL_STEELWALL_BOTTOMLEFT, EL_INVISIBLE_STEELWALL_BOTTOMLEFT },
1080 { EL_STEELWALL_BOTTOMRIGHT, EL_INVISIBLE_STEELWALL_BOTTOMRIGHT },
1081 { EL_STEELWALL_VERTICAL, EL_INVISIBLE_STEELWALL_VERTICAL },
1082 { EL_STEELWALL_HORIZONTAL, EL_INVISIBLE_STEELWALL_HORIZONTAL },
1083 { EL_STEELWALL, EL_INVISIBLE_STEELWALL }
1085 int steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
1086 int steel_position = (x == -1 && y == -1 ? 0 :
1087 x == lev_fieldx && y == -1 ? 1 :
1088 x == -1 && y == lev_fieldy ? 2 :
1089 x == lev_fieldx && y == lev_fieldy ? 3 :
1090 x == -1 || x == lev_fieldx ? 4 :
1091 y == -1 || y == lev_fieldy ? 5 : 6);
1093 return border[steel_position][steel_type];
1096 void DrawScreenElement(int x, int y, int element)
1098 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1099 DrawLevelFieldCrumbledSand(LEVELX(x), LEVELY(y));
1102 void DrawLevelElement(int x, int y, int element)
1104 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1105 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1108 void DrawScreenField(int x, int y)
1110 int lx = LEVELX(x), ly = LEVELY(y);
1111 int element, content;
1113 if (!IN_LEV_FIELD(lx, ly))
1115 if (lx < -1 || lx > lev_fieldx || ly < -1 || ly > lev_fieldy)
1118 element = getBorderElement(lx, ly);
1120 DrawScreenElement(x, y, element);
1124 element = Feld[lx][ly];
1125 content = Store[lx][ly];
1127 if (IS_MOVING(lx, ly))
1129 int horiz_move = (MovDir[lx][ly] == MV_LEFT || MovDir[lx][ly] == MV_RIGHT);
1130 boolean cut_mode = NO_CUTTING;
1132 if (element == EL_QUICKSAND_EMPTYING ||
1133 element == EL_MAGIC_WALL_EMPTYING ||
1134 element == EL_BD_MAGIC_WALL_EMPTYING ||
1135 element == EL_AMOEBA_DROPPING)
1136 cut_mode = CUT_ABOVE;
1137 else if (element == EL_QUICKSAND_FILLING ||
1138 element == EL_MAGIC_WALL_FILLING ||
1139 element == EL_BD_MAGIC_WALL_FILLING)
1140 cut_mode = CUT_BELOW;
1142 if (cut_mode == CUT_ABOVE)
1143 DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1145 DrawScreenElement(x, y, EL_EMPTY);
1148 DrawScreenElementShifted(x, y, MovPos[lx][ly], 0, element, NO_CUTTING);
1149 else if (cut_mode == NO_CUTTING)
1150 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], element, cut_mode);
1152 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], content, cut_mode);
1154 if (content == EL_ACID)
1156 int dir = MovDir[lx][ly];
1157 int newlx = lx + (dir == MV_LEFT ? -1 : dir == MV_RIGHT ? +1 : 0);
1158 int newly = ly + (dir == MV_UP ? -1 : dir == MV_DOWN ? +1 : 0);
1160 DrawLevelElementThruMask(newlx, newly, EL_ACID);
1163 else if (IS_BLOCKED(lx, ly))
1168 boolean cut_mode = NO_CUTTING;
1169 int element_old, content_old;
1171 Blocked2Moving(lx, ly, &oldx, &oldy);
1174 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1175 MovDir[oldx][oldy] == MV_RIGHT);
1177 element_old = Feld[oldx][oldy];
1178 content_old = Store[oldx][oldy];
1180 if (element_old == EL_QUICKSAND_EMPTYING ||
1181 element_old == EL_MAGIC_WALL_EMPTYING ||
1182 element_old == EL_BD_MAGIC_WALL_EMPTYING ||
1183 element_old == EL_AMOEBA_DROPPING)
1184 cut_mode = CUT_ABOVE;
1186 DrawScreenElement(x, y, EL_EMPTY);
1189 DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
1191 else if (cut_mode == NO_CUTTING)
1192 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
1195 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
1198 else if (IS_DRAWABLE(element))
1199 DrawScreenElement(x, y, element);
1201 DrawScreenElement(x, y, EL_EMPTY);
1204 void DrawLevelField(int x, int y)
1206 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1207 DrawScreenField(SCREENX(x), SCREENY(y));
1208 else if (IS_MOVING(x, y))
1212 Moving2Blocked(x, y, &newx, &newy);
1213 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1214 DrawScreenField(SCREENX(newx), SCREENY(newy));
1216 else if (IS_BLOCKED(x, y))
1220 Blocked2Moving(x, y, &oldx, &oldy);
1221 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1222 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1226 void DrawMiniElement(int x, int y, int element)
1230 graphic = el2edimg(element);
1231 DrawMiniGraphic(x, y, graphic);
1234 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1236 int x = sx + scroll_x, y = sy + scroll_y;
1238 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1239 DrawMiniElement(sx, sy, EL_EMPTY);
1240 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1241 DrawMiniElement(sx, sy, Feld[x][y]);
1243 DrawMiniGraphic(sx, sy, el2edimg(getBorderElement(x, y)));
1246 void DrawEnvelopeBackground(int envelope_nr, int startx, int starty,
1247 int x, int y, int xsize, int ysize, int font_nr)
1249 int font_width = getFontWidth(font_nr);
1250 int font_height = getFontHeight(font_nr);
1251 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1254 int dst_x = SX + startx + x * font_width;
1255 int dst_y = SY + starty + y * font_height;
1256 int width = graphic_info[graphic].width;
1257 int height = graphic_info[graphic].height;
1258 int inner_width = MAX(width - 2 * font_width, font_width);
1259 int inner_height = MAX(height - 2 * font_height, font_height);
1260 int inner_sx = (width >= 3 * font_width ? font_width : 0);
1261 int inner_sy = (height >= 3 * font_height ? font_height : 0);
1262 boolean draw_masked = graphic_info[graphic].draw_masked;
1264 getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
1266 if (src_bitmap == NULL || width < font_width || height < font_height)
1268 ClearRectangle(drawto, dst_x, dst_y, font_width, font_height);
1272 src_x += (x == 0 ? 0 : x == xsize - 1 ? width - font_width :
1273 inner_sx + (x - 1) * font_width % inner_width);
1274 src_y += (y == 0 ? 0 : y == ysize - 1 ? height - font_height :
1275 inner_sy + (y - 1) * font_height % inner_height);
1279 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1280 dst_x - src_x, dst_y - src_y);
1281 BlitBitmapMasked(src_bitmap, drawto, src_x, src_y, font_width, font_height,
1285 BlitBitmap(src_bitmap, drawto, src_x, src_y, font_width, font_height,
1289 void AnimateEnvelope(int envelope_nr, int anim_mode, int action)
1291 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1292 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
1293 int mask_mode = (src_bitmap != NULL ? BLIT_MASKED : BLIT_ON_BACKGROUND);
1294 boolean ffwd_delay = (tape.playing && tape.fast_forward);
1295 boolean no_delay = (tape.warp_forward);
1296 unsigned long anim_delay = 0;
1297 int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
1298 int anim_delay_value = (no_delay ? 0 : frame_delay_value);
1299 int font_nr = FONT_ENVELOPE_1 + envelope_nr;
1300 int font_width = getFontWidth(font_nr);
1301 int font_height = getFontHeight(font_nr);
1302 int max_xsize = level.envelope_xsize[envelope_nr];
1303 int max_ysize = level.envelope_ysize[envelope_nr];
1304 int xstart = (anim_mode & ANIM_VERTICAL ? max_xsize : 0);
1305 int ystart = (anim_mode & ANIM_HORIZONTAL ? max_ysize : 0);
1306 int xend = max_xsize;
1307 int yend = (anim_mode != ANIM_DEFAULT ? max_ysize : 0);
1308 int xstep = (xstart < xend ? 1 : 0);
1309 int ystep = (ystart < yend || xstep == 0 ? 1 : 0);
1312 for (x = xstart, y = ystart; x <= xend && y <= yend; x += xstep, y += ystep)
1314 int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2;
1315 int ysize = (action == ACTION_CLOSING ? yend - (y - ystart) : y) + 2;
1316 int sx = (SXSIZE - xsize * font_width) / 2;
1317 int sy = (SYSIZE - ysize * font_height) / 2;
1320 SetDrawtoField(DRAW_BUFFERED);
1322 BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
1324 SetDrawtoField(DRAW_BACKBUFFER);
1326 for (yy = 0; yy < ysize; yy++) for (xx = 0; xx < xsize; xx++)
1327 DrawEnvelopeBackground(envelope_nr, sx,sy, xx,yy, xsize, ysize, font_nr);
1329 DrawTextToTextArea(SX + sx + font_width, SY + sy + font_height,
1330 level.envelope_text[envelope_nr], font_nr, max_xsize,
1331 xsize - 2, ysize - 2, mask_mode);
1333 redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
1336 WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
1340 void ShowEnvelope(int envelope_nr)
1342 int element = EL_ENVELOPE_1 + envelope_nr;
1343 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1344 int sound_opening = element_info[element].sound[ACTION_OPENING];
1345 int sound_closing = element_info[element].sound[ACTION_CLOSING];
1346 boolean ffwd_delay = (tape.playing && tape.fast_forward);
1347 boolean no_delay = (tape.warp_forward);
1348 int normal_delay_value = ONE_SECOND_DELAY / (ffwd_delay ? 2 : 1);
1349 int wait_delay_value = (no_delay ? 0 : normal_delay_value);
1350 int anim_mode = graphic_info[graphic].anim_mode;
1351 int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL:
1352 anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode);
1354 game.envelope_active = TRUE; /* needed for RedrawPlayfield() events */
1356 PlaySoundStereo(sound_opening, SOUND_MIDDLE);
1358 if (anim_mode == ANIM_DEFAULT)
1359 AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_OPENING);
1361 AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_OPENING);
1364 Delay(wait_delay_value);
1366 WaitForEventToContinue();
1368 PlaySoundStereo(sound_closing, SOUND_MIDDLE);
1370 if (anim_mode != ANIM_NONE)
1371 AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_CLOSING);
1373 if (anim_mode == ANIM_DEFAULT)
1374 AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_CLOSING);
1376 game.envelope_active = FALSE;
1378 SetDrawtoField(DRAW_BUFFERED);
1380 redraw_mask |= REDRAW_FIELD;
1384 void getMicroGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1386 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
1387 int mini_startx = src_bitmap->width * 3 / 4;
1388 int mini_starty = src_bitmap->height * 2 / 3;
1389 int src_x = mini_startx + graphic_info[graphic].src_x / 8;
1390 int src_y = mini_starty + graphic_info[graphic].src_y / 8;
1392 *bitmap = src_bitmap;
1397 void DrawMicroElement(int xpos, int ypos, int element)
1401 int graphic = el2preimg(element);
1403 getMicroGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1404 BlitBitmap(src_bitmap, drawto, src_x, src_y, MICRO_TILEX, MICRO_TILEY,
1412 SetDrawBackgroundMask(REDRAW_NONE);
1415 for (x = BX1; x <= BX2; x++)
1416 for (y = BY1; y <= BY2; y++)
1417 DrawScreenField(x, y);
1419 redraw_mask |= REDRAW_FIELD;
1422 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1426 for (x = 0; x < size_x; x++)
1427 for (y = 0; y < size_y; y++)
1428 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1430 redraw_mask |= REDRAW_FIELD;
1433 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1437 DrawBackground(xpos, ypos, MICROLEVEL_XSIZE, MICROLEVEL_YSIZE);
1439 if (lev_fieldx < STD_LEV_FIELDX)
1440 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1441 if (lev_fieldy < STD_LEV_FIELDY)
1442 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1444 xpos += MICRO_TILEX;
1445 ypos += MICRO_TILEY;
1447 for (x = -1; x <= STD_LEV_FIELDX; x++)
1449 for (y = -1; y <= STD_LEV_FIELDY; y++)
1451 int lx = from_x + x, ly = from_y + y;
1453 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1454 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1455 level.field[lx][ly]);
1456 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1
1457 && BorderElement != EL_EMPTY)
1458 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1459 getBorderElement(lx, ly));
1463 redraw_mask |= REDRAW_MICROLEVEL;
1466 #define MICROLABEL_EMPTY 0
1467 #define MICROLABEL_LEVEL_NAME 1
1468 #define MICROLABEL_LEVEL_AUTHOR_HEAD 2
1469 #define MICROLABEL_LEVEL_AUTHOR 3
1470 #define MICROLABEL_IMPORTED_FROM_HEAD 4
1471 #define MICROLABEL_IMPORTED_FROM 5
1472 #define MICROLABEL_IMPORTED_BY_HEAD 6
1473 #define MICROLABEL_IMPORTED_BY 7
1475 static void DrawMicroLevelLabelExt(int mode)
1477 char label_text[MAX_OUTPUT_LINESIZE + 1];
1478 int max_len_label_text;
1479 int font_nr = FONT_TEXT_2;
1482 if (mode == MICROLABEL_LEVEL_AUTHOR_HEAD ||
1483 mode == MICROLABEL_IMPORTED_FROM_HEAD ||
1484 mode == MICROLABEL_IMPORTED_BY_HEAD)
1485 font_nr = FONT_TEXT_3;
1487 max_len_label_text = SXSIZE / getFontWidth(font_nr);
1489 for (i = 0; i < max_len_label_text; i++)
1490 label_text[i] = ' ';
1491 label_text[max_len_label_text] = '\0';
1493 if (strlen(label_text) > 0)
1495 int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
1496 int lypos = MICROLABEL2_YPOS;
1498 DrawText(lxpos, lypos, label_text, font_nr);
1502 (mode == MICROLABEL_LEVEL_NAME ? level.name :
1503 mode == MICROLABEL_LEVEL_AUTHOR_HEAD ? "created by" :
1504 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
1505 mode == MICROLABEL_IMPORTED_FROM_HEAD ? "imported from" :
1506 mode == MICROLABEL_IMPORTED_FROM ? leveldir_current->imported_from :
1507 mode == MICROLABEL_IMPORTED_BY_HEAD ? "imported by" :
1508 mode == MICROLABEL_IMPORTED_BY ? leveldir_current->imported_by :""),
1509 max_len_label_text);
1510 label_text[max_len_label_text] = '\0';
1512 if (strlen(label_text) > 0)
1514 int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
1515 int lypos = MICROLABEL2_YPOS;
1517 DrawText(lxpos, lypos, label_text, font_nr);
1520 redraw_mask |= REDRAW_MICROLEVEL;
1523 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1525 static unsigned long scroll_delay = 0;
1526 static unsigned long label_delay = 0;
1527 static int from_x, from_y, scroll_direction;
1528 static int label_state, label_counter;
1529 int last_game_status = game_status; /* save current game status */
1531 /* force PREVIEW font on preview level */
1532 game_status = GAME_MODE_PSEUDO_PREVIEW;
1536 from_x = from_y = 0;
1537 scroll_direction = MV_RIGHT;
1541 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1542 DrawMicroLevelLabelExt(label_state);
1544 /* initialize delay counters */
1545 DelayReached(&scroll_delay, 0);
1546 DelayReached(&label_delay, 0);
1548 if (leveldir_current->name)
1550 char label_text[MAX_OUTPUT_LINESIZE + 1];
1551 int font_nr = FONT_TEXT_1;
1552 int max_len_label_text = SXSIZE / getFontWidth(font_nr);
1555 strncpy(label_text, leveldir_current->name, max_len_label_text);
1556 label_text[max_len_label_text] = '\0';
1558 lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
1559 lypos = SY + MICROLABEL1_YPOS;
1561 DrawText(lxpos, lypos, label_text, font_nr);
1564 game_status = last_game_status; /* restore current game status */
1569 /* scroll micro level, if needed */
1570 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1571 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1573 switch (scroll_direction)
1579 scroll_direction = MV_UP;
1583 if (from_x < lev_fieldx - STD_LEV_FIELDX)
1586 scroll_direction = MV_DOWN;
1593 scroll_direction = MV_RIGHT;
1597 if (from_y < lev_fieldy - STD_LEV_FIELDY)
1600 scroll_direction = MV_LEFT;
1607 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1610 /* !!! THIS ALL SUCKS -- SHOULD BE CLEANLY REWRITTEN !!! */
1611 /* redraw micro level label, if needed */
1612 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1613 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1614 strcmp(level.author, leveldir_current->name) != 0 &&
1615 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1617 int max_label_counter = 23;
1619 if (leveldir_current->imported_from != NULL &&
1620 strlen(leveldir_current->imported_from) > 0)
1621 max_label_counter += 14;
1622 if (leveldir_current->imported_by != NULL &&
1623 strlen(leveldir_current->imported_by) > 0)
1624 max_label_counter += 14;
1626 label_counter = (label_counter + 1) % max_label_counter;
1627 label_state = (label_counter >= 0 && label_counter <= 7 ?
1628 MICROLABEL_LEVEL_NAME :
1629 label_counter >= 9 && label_counter <= 12 ?
1630 MICROLABEL_LEVEL_AUTHOR_HEAD :
1631 label_counter >= 14 && label_counter <= 21 ?
1632 MICROLABEL_LEVEL_AUTHOR :
1633 label_counter >= 23 && label_counter <= 26 ?
1634 MICROLABEL_IMPORTED_FROM_HEAD :
1635 label_counter >= 28 && label_counter <= 35 ?
1636 MICROLABEL_IMPORTED_FROM :
1637 label_counter >= 37 && label_counter <= 40 ?
1638 MICROLABEL_IMPORTED_BY_HEAD :
1639 label_counter >= 42 && label_counter <= 49 ?
1640 MICROLABEL_IMPORTED_BY : MICROLABEL_EMPTY);
1642 if (leveldir_current->imported_from == NULL &&
1643 (label_state == MICROLABEL_IMPORTED_FROM_HEAD ||
1644 label_state == MICROLABEL_IMPORTED_FROM))
1645 label_state = (label_state == MICROLABEL_IMPORTED_FROM_HEAD ?
1646 MICROLABEL_IMPORTED_BY_HEAD : MICROLABEL_IMPORTED_BY);
1648 DrawMicroLevelLabelExt(label_state);
1651 game_status = last_game_status; /* restore current game status */
1654 inline void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
1655 int graphic, int sync_frame, int mask_mode)
1657 int frame = getGraphicAnimationFrame(graphic, sync_frame);
1659 if (mask_mode == USE_MASKING)
1660 DrawGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
1662 DrawGraphicExt(dst_bitmap, x, y, graphic, frame);
1665 inline void DrawGraphicAnimation(int x, int y, int graphic)
1667 int lx = LEVELX(x), ly = LEVELY(y);
1669 if (!IN_SCR_FIELD(x, y))
1672 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
1673 graphic, GfxFrame[lx][ly], NO_MASKING);
1674 MarkTileDirty(x, y);
1677 void DrawLevelGraphicAnimation(int x, int y, int graphic)
1679 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
1682 void DrawLevelElementAnimation(int x, int y, int element)
1684 int graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
1686 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
1689 inline void DrawLevelGraphicAnimationIfNeeded(int x, int y, int graphic)
1691 int sx = SCREENX(x), sy = SCREENY(y);
1693 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
1696 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
1699 DrawGraphicAnimation(sx, sy, graphic);
1701 if (GFX_CRUMBLED(Feld[x][y]))
1702 DrawLevelFieldCrumbledSand(x, y);
1705 void DrawLevelElementAnimationIfNeeded(int x, int y, int element)
1707 int sx = SCREENX(x), sy = SCREENY(y);
1710 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
1713 graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
1715 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
1718 DrawGraphicAnimation(sx, sy, graphic);
1720 if (GFX_CRUMBLED(element))
1721 DrawLevelFieldCrumbledSand(x, y);
1724 static int getPlayerGraphic(struct PlayerInfo *player, int move_dir)
1726 if (player->use_murphy_graphic)
1728 /* this works only because currently only one player can be "murphy" ... */
1729 static int last_horizontal_dir = MV_LEFT;
1730 int graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, move_dir);
1732 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
1733 last_horizontal_dir = move_dir;
1735 if (graphic == IMG_SP_MURPHY) /* undefined => use special graphic */
1737 int direction = (player->is_snapping ? move_dir : last_horizontal_dir);
1739 graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, direction);
1745 return el_act_dir2img(player->element_nr, player->GfxAction, move_dir);
1748 static boolean equalGraphics(int graphic1, int graphic2)
1750 struct GraphicInfo *g1 = &graphic_info[graphic1];
1751 struct GraphicInfo *g2 = &graphic_info[graphic2];
1753 return (g1->bitmap == g2->bitmap &&
1754 g1->src_x == g2->src_x &&
1755 g1->src_y == g2->src_y &&
1756 g1->anim_frames == g2->anim_frames &&
1757 g1->anim_delay == g2->anim_delay &&
1758 g1->anim_mode == g2->anim_mode);
1761 void DrawAllPlayers()
1765 for (i = 0; i < MAX_PLAYERS; i++)
1766 if (stored_player[i].active)
1767 DrawPlayer(&stored_player[i]);
1770 void DrawPlayerField(int x, int y)
1772 if (!IS_PLAYER(x, y))
1775 DrawPlayer(PLAYERINFO(x, y));
1778 void DrawPlayer(struct PlayerInfo *player)
1780 int jx = player->jx;
1781 int jy = player->jy;
1782 int move_dir = player->MovDir;
1783 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? +1 : 0);
1784 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? +1 : 0);
1785 int last_jx = (player->is_moving ? jx - dx : jx);
1786 int last_jy = (player->is_moving ? jy - dy : jy);
1787 int next_jx = jx + dx;
1788 int next_jy = jy + dy;
1789 boolean player_is_moving = (player->MovPos ? TRUE : FALSE);
1790 int sx = SCREENX(jx), sy = SCREENY(jy);
1791 int sxx = 0, syy = 0;
1792 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
1794 int action = ACTION_DEFAULT;
1795 int last_player_graphic = getPlayerGraphic(player, move_dir);
1796 int last_player_frame = player->Frame;
1799 if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
1803 if (!IN_LEV_FIELD(jx, jy))
1805 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
1806 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
1807 printf("DrawPlayerField(): This should never happen!\n");
1812 if (element == EL_EXPLOSION)
1815 action = (player->is_pushing ? ACTION_PUSHING :
1816 player->is_digging ? ACTION_DIGGING :
1817 player->is_collecting ? ACTION_COLLECTING :
1818 player->is_moving ? ACTION_MOVING :
1819 player->is_snapping ? ACTION_SNAPPING :
1820 player->is_dropping ? ACTION_DROPPING :
1821 player->is_waiting ? player->action_waiting : ACTION_DEFAULT);
1823 InitPlayerGfxAnimation(player, action, move_dir);
1825 /* ----------------------------------------------------------------------- */
1826 /* draw things in the field the player is leaving, if needed */
1827 /* ----------------------------------------------------------------------- */
1829 if (player->is_moving)
1831 if (Back[last_jx][last_jy] && IS_DRAWABLE(last_element))
1833 DrawLevelElement(last_jx, last_jy, Back[last_jx][last_jy]);
1835 if (last_element == EL_DYNAMITE_ACTIVE ||
1836 last_element == EL_SP_DISK_RED_ACTIVE)
1837 DrawDynamite(last_jx, last_jy);
1839 DrawLevelFieldThruMask(last_jx, last_jy);
1841 else if (last_element == EL_DYNAMITE_ACTIVE ||
1842 last_element == EL_SP_DISK_RED_ACTIVE)
1843 DrawDynamite(last_jx, last_jy);
1845 DrawLevelField(last_jx, last_jy);
1847 if (player->is_pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
1848 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
1851 if (!IN_SCR_FIELD(sx, sy))
1854 if (setup.direct_draw)
1855 SetDrawtoField(DRAW_BUFFERED);
1857 /* ----------------------------------------------------------------------- */
1858 /* draw things behind the player, if needed */
1859 /* ----------------------------------------------------------------------- */
1862 DrawLevelElement(jx, jy, Back[jx][jy]);
1863 else if (IS_ACTIVE_BOMB(element))
1864 DrawLevelElement(jx, jy, EL_EMPTY);
1867 if (player_is_moving && GfxElement[jx][jy] != EL_UNDEFINED)
1869 if (GFX_CRUMBLED(GfxElement[jx][jy]))
1870 DrawLevelFieldCrumbledSandDigging(jx, jy, move_dir, player->StepFrame);
1873 int old_element = GfxElement[jx][jy];
1874 int old_graphic = el_act_dir2img(old_element, action, move_dir);
1875 int frame = getGraphicAnimationFrame(old_graphic, player->StepFrame);
1877 DrawGraphic(sx, sy, old_graphic, frame);
1882 GfxElement[jx][jy] = EL_UNDEFINED;
1884 /* make sure that pushed elements are drawn with correct frame rate */
1885 if (player->is_pushing && player->is_moving)
1886 GfxFrame[jx][jy] = player->StepFrame;
1888 DrawLevelField(jx, jy);
1892 /* ----------------------------------------------------------------------- */
1893 /* draw player himself */
1894 /* ----------------------------------------------------------------------- */
1896 graphic = getPlayerGraphic(player, move_dir);
1898 /* in the case of changed player action or direction, prevent the current
1899 animation frame from being restarted for identical animations */
1900 if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic))
1901 player->Frame = last_player_frame;
1903 frame = getGraphicAnimationFrame(graphic, player->Frame);
1907 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
1908 sxx = player->GfxPos;
1910 syy = player->GfxPos;
1913 if (!setup.soft_scrolling && ScreenMovPos)
1916 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
1918 if (SHIELD_ON(player))
1920 int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
1921 IMG_SHIELD_NORMAL_ACTIVE);
1922 int frame = getGraphicAnimationFrame(graphic, -1);
1924 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
1927 /* ----------------------------------------------------------------------- */
1928 /* draw things the player is pushing, if needed */
1929 /* ----------------------------------------------------------------------- */
1932 printf("::: %d, %d [%d, %d] [%d]\n",
1933 player->is_pushing, player_is_moving, player->GfxAction,
1934 player->is_moving, player_is_moving);
1938 if (player->is_pushing && player->is_moving)
1940 int px = SCREENX(jx), py = SCREENY(jy);
1941 int pxx = (TILEX - ABS(sxx)) * dx;
1942 int pyy = (TILEY - ABS(syy)) * dy;
1947 if (!IS_MOVING(jx, jy)) /* push movement already finished */
1948 element = Feld[next_jx][next_jy];
1950 graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
1951 frame = getGraphicAnimationFrame(graphic, player->StepFrame);
1953 /* draw background element under pushed element (like the Sokoban field) */
1954 if (Back[next_jx][next_jy])
1955 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
1957 /* masked drawing is needed for EMC style (double) movement graphics */
1958 DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame, NO_CUTTING);
1962 /* ----------------------------------------------------------------------- */
1963 /* draw things in front of player (active dynamite or dynabombs) */
1964 /* ----------------------------------------------------------------------- */
1966 if (IS_ACTIVE_BOMB(element))
1968 graphic = el2img(element);
1969 frame = getGraphicAnimationFrame(graphic, GfxFrame[jx][jy]);
1971 if (game.emulation == EMU_SUPAPLEX)
1972 DrawGraphic(sx, sy, IMG_SP_DISK_RED, frame);
1974 DrawGraphicThruMask(sx, sy, graphic, frame);
1977 if (player_is_moving && last_element == EL_EXPLOSION)
1979 int graphic = el_act2img(GfxElement[last_jx][last_jy], ACTION_EXPLODING);
1980 int delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2);
1981 int phase = ExplodePhase[last_jx][last_jy] - 1;
1982 int frame = getGraphicAnimationFrame(graphic, phase - delay);
1985 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy), graphic, frame);
1988 /* ----------------------------------------------------------------------- */
1989 /* draw elements the player is just walking/passing through/under */
1990 /* ----------------------------------------------------------------------- */
1992 if (player_is_moving)
1994 /* handle the field the player is leaving ... */
1995 if (IS_ACCESSIBLE_INSIDE(last_element))
1996 DrawLevelField(last_jx, last_jy);
1997 else if (IS_ACCESSIBLE_UNDER(last_element))
1998 DrawLevelFieldThruMask(last_jx, last_jy);
2001 /* do not redraw accessible elements if the player is just pushing them */
2002 if (!player_is_moving || !player->is_pushing)
2004 /* ... and the field the player is entering */
2005 if (IS_ACCESSIBLE_INSIDE(element))
2006 DrawLevelField(jx, jy);
2007 else if (IS_ACCESSIBLE_UNDER(element))
2008 DrawLevelFieldThruMask(jx, jy);
2011 if (setup.direct_draw)
2013 int dst_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
2014 int dst_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
2015 int x_size = TILEX * (1 + ABS(jx - last_jx));
2016 int y_size = TILEY * (1 + ABS(jy - last_jy));
2018 BlitBitmap(drawto_field, window,
2019 dst_x, dst_y, x_size, y_size, dst_x, dst_y);
2020 SetDrawtoField(DRAW_DIRECT);
2023 MarkTileDirty(sx, sy);
2026 /* ------------------------------------------------------------------------- */
2028 void WaitForEventToContinue()
2030 boolean still_wait = TRUE;
2032 /* simulate releasing mouse button over last gadget, if still pressed */
2034 HandleGadgets(-1, -1, 0);
2036 button_status = MB_RELEASED;
2048 case EVENT_BUTTONPRESS:
2049 case EVENT_KEYPRESS:
2053 case EVENT_KEYRELEASE:
2054 ClearPlayerAction();
2058 HandleOtherEvents(&event);
2062 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2069 /* don't eat all CPU time */
2074 #define MAX_REQUEST_LINES 13
2075 #define MAX_REQUEST_LINE_FONT1_LEN 7
2076 #define MAX_REQUEST_LINE_FONT2_LEN 10
2078 boolean Request(char *text, unsigned int req_state)
2080 int mx, my, ty, result = -1;
2081 unsigned int old_door_state;
2082 int last_game_status = game_status; /* save current game status */
2083 int max_request_line_len = MAX_REQUEST_LINE_FONT1_LEN;
2084 int font_nr = FONT_TEXT_2;
2085 int max_word_len = 0;
2088 for (text_ptr = text; *text_ptr; text_ptr++)
2090 max_word_len = (*text_ptr != ' ' ? max_word_len + 1 : 0);
2092 if (max_word_len > MAX_REQUEST_LINE_FONT1_LEN)
2094 max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
2095 font_nr = FONT_LEVEL_NUMBER;
2101 if (game_status == GAME_MODE_PLAYING &&
2102 level.game_engine_type == GAME_ENGINE_TYPE_EM)
2103 BlitScreenToBitmap_EM(backbuffer);
2105 /* disable deactivated drawing when quick-loading level tape recording */
2106 if (tape.playing && tape.deactivate_display)
2107 TapeDeactivateDisplayOff(TRUE);
2109 SetMouseCursor(CURSOR_DEFAULT);
2111 #if defined(NETWORK_AVALIABLE)
2112 /* pause network game while waiting for request to answer */
2113 if (options.network &&
2114 game_status == GAME_MODE_PLAYING &&
2115 req_state & REQUEST_WAIT_FOR_INPUT)
2116 SendToServer_PausePlaying();
2119 old_door_state = GetDoorState();
2121 /* simulate releasing mouse button over last gadget, if still pressed */
2123 HandleGadgets(-1, -1, 0);
2127 if (old_door_state & DOOR_OPEN_1)
2129 CloseDoor(DOOR_CLOSE_1);
2131 /* save old door content */
2132 BlitBitmap(bitmap_db_door, bitmap_db_door,
2133 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
2134 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
2137 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
2139 /* clear door drawing field */
2140 DrawBackground(DX, DY, DXSIZE, DYSIZE);
2142 /* force DOOR font on preview level */
2143 game_status = GAME_MODE_PSEUDO_DOOR;
2145 /* write text for request */
2146 for (ty = 0; ty < MAX_REQUEST_LINES; ty++)
2148 char text_line[max_request_line_len + 1];
2154 for (tl = 0, tx = 0; tx < max_request_line_len; tl++, tx++)
2157 if (!tc || tc == ' ')
2168 strncpy(text_line, text, tl);
2171 DrawText(DX + (DXSIZE - tl * getFontWidth(font_nr)) / 2,
2172 DY + 8 + ty * (getFontHeight(font_nr) + 2),
2173 text_line, font_nr);
2175 text += tl + (tc == ' ' ? 1 : 0);
2178 game_status = last_game_status; /* restore current game status */
2180 if (req_state & REQ_ASK)
2182 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
2183 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
2185 else if (req_state & REQ_CONFIRM)
2187 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
2189 else if (req_state & REQ_PLAYER)
2191 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
2192 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
2193 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
2194 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
2197 /* copy request gadgets to door backbuffer */
2198 BlitBitmap(drawto, bitmap_db_door,
2199 DX, DY, DXSIZE, DYSIZE,
2200 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2202 OpenDoor(DOOR_OPEN_1);
2204 if (!(req_state & REQUEST_WAIT_FOR_INPUT))
2206 SetDrawBackgroundMask(REDRAW_FIELD);
2211 if (game_status != GAME_MODE_MAIN)
2214 button_status = MB_RELEASED;
2216 request_gadget_id = -1;
2218 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
2230 case EVENT_BUTTONPRESS:
2231 case EVENT_BUTTONRELEASE:
2232 case EVENT_MOTIONNOTIFY:
2234 if (event.type == EVENT_MOTIONNOTIFY)
2236 if (!PointerInWindow(window))
2237 continue; /* window and pointer are on different screens */
2242 motion_status = TRUE;
2243 mx = ((MotionEvent *) &event)->x;
2244 my = ((MotionEvent *) &event)->y;
2248 motion_status = FALSE;
2249 mx = ((ButtonEvent *) &event)->x;
2250 my = ((ButtonEvent *) &event)->y;
2251 if (event.type == EVENT_BUTTONPRESS)
2252 button_status = ((ButtonEvent *) &event)->button;
2254 button_status = MB_RELEASED;
2257 /* this sets 'request_gadget_id' */
2258 HandleGadgets(mx, my, button_status);
2260 switch(request_gadget_id)
2262 case TOOL_CTRL_ID_YES:
2265 case TOOL_CTRL_ID_NO:
2268 case TOOL_CTRL_ID_CONFIRM:
2269 result = TRUE | FALSE;
2272 case TOOL_CTRL_ID_PLAYER_1:
2275 case TOOL_CTRL_ID_PLAYER_2:
2278 case TOOL_CTRL_ID_PLAYER_3:
2281 case TOOL_CTRL_ID_PLAYER_4:
2292 case EVENT_KEYPRESS:
2293 switch(GetEventKey((KeyEvent *)&event, TRUE))
2306 if (req_state & REQ_PLAYER)
2310 case EVENT_KEYRELEASE:
2311 ClearPlayerAction();
2315 HandleOtherEvents(&event);
2319 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2321 int joy = AnyJoystick();
2323 if (joy & JOY_BUTTON_1)
2325 else if (joy & JOY_BUTTON_2)
2331 /* don't eat all CPU time */
2335 if (game_status != GAME_MODE_MAIN)
2340 if (!(req_state & REQ_STAY_OPEN))
2342 CloseDoor(DOOR_CLOSE_1);
2344 if (((old_door_state & DOOR_OPEN_1) && !(req_state & REQ_STAY_CLOSED)) ||
2345 (req_state & REQ_REOPEN))
2346 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
2351 SetDrawBackgroundMask(REDRAW_FIELD);
2353 #if defined(NETWORK_AVALIABLE)
2354 /* continue network game after request */
2355 if (options.network &&
2356 game_status == GAME_MODE_PLAYING &&
2357 req_state & REQUEST_WAIT_FOR_INPUT)
2358 SendToServer_ContinuePlaying();
2361 /* restore deactivated drawing when quick-loading level tape recording */
2362 if (tape.playing && tape.deactivate_display)
2363 TapeDeactivateDisplayOn();
2368 unsigned int OpenDoor(unsigned int door_state)
2370 if (door_state & DOOR_COPY_BACK)
2372 if (door_state & DOOR_OPEN_1)
2373 BlitBitmap(bitmap_db_door, bitmap_db_door,
2374 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
2375 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2377 if (door_state & DOOR_OPEN_2)
2378 BlitBitmap(bitmap_db_door, bitmap_db_door,
2379 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY2, VXSIZE, VYSIZE,
2380 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2382 door_state &= ~DOOR_COPY_BACK;
2385 return MoveDoor(door_state);
2388 unsigned int CloseDoor(unsigned int door_state)
2390 unsigned int old_door_state = GetDoorState();
2392 if (!(door_state & DOOR_NO_COPY_BACK))
2394 if (old_door_state & DOOR_OPEN_1)
2395 BlitBitmap(backbuffer, bitmap_db_door,
2396 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2398 if (old_door_state & DOOR_OPEN_2)
2399 BlitBitmap(backbuffer, bitmap_db_door,
2400 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2402 door_state &= ~DOOR_NO_COPY_BACK;
2405 return MoveDoor(door_state);
2408 unsigned int GetDoorState()
2410 return MoveDoor(DOOR_GET_STATE);
2413 unsigned int SetDoorState(unsigned int door_state)
2415 return MoveDoor(door_state | DOOR_SET_STATE);
2418 unsigned int MoveDoor(unsigned int door_state)
2420 static int door1 = DOOR_OPEN_1;
2421 static int door2 = DOOR_CLOSE_2;
2422 unsigned long door_delay = 0;
2423 unsigned long door_delay_value;
2426 if (door_state == DOOR_GET_STATE)
2427 return(door1 | door2);
2429 if (door_state & DOOR_SET_STATE)
2431 if (door_state & DOOR_ACTION_1)
2432 door1 = door_state & DOOR_ACTION_1;
2433 if (door_state & DOOR_ACTION_2)
2434 door2 = door_state & DOOR_ACTION_2;
2436 return(door1 | door2);
2439 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2440 door_state &= ~DOOR_OPEN_1;
2441 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2442 door_state &= ~DOOR_CLOSE_1;
2443 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2444 door_state &= ~DOOR_OPEN_2;
2445 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2446 door_state &= ~DOOR_CLOSE_2;
2448 door_delay_value = (door_state & DOOR_ACTION_1 ? door_1.step_delay :
2451 if (setup.quick_doors)
2453 stepsize = 20; /* must be choosen to always draw last frame */
2454 door_delay_value = 0;
2457 if (global.autoplay_leveldir)
2459 door_state |= DOOR_NO_DELAY;
2460 door_state &= ~DOOR_CLOSE_ALL;
2463 if (door_state & DOOR_ACTION)
2465 boolean door_1_done = !(door_state & DOOR_ACTION_1);
2466 boolean door_2_done = !(door_state & DOOR_ACTION_2);
2467 int start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2468 int end = (door_state & DOOR_ACTION_1 &&
2469 door_1.anim_mode == ANIM_VERTICAL ? DYSIZE : DXSIZE);
2472 if (!(door_state & DOOR_NO_DELAY) && !setup.quick_doors)
2474 /* opening door sound has priority over simultaneously closing door */
2475 if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
2476 PlaySoundStereo(SND_DOOR_OPENING, SOUND_MIDDLE);
2477 else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
2478 PlaySoundStereo(SND_DOOR_CLOSING, SOUND_MIDDLE);
2481 for (x = start; x <= end && !(door_1_done && door_2_done); x += stepsize)
2483 Bitmap *bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2484 GC gc = bitmap->stored_clip_gc;
2486 if (door_state & DOOR_ACTION_1)
2488 int a = MIN(x * door_1.step_offset, end);
2489 int i = (door_state & DOOR_OPEN_1 ? end - a : a);
2493 BlitBitmap(bitmap_db_door, drawto,
2494 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i / 2,
2495 DXSIZE, DYSIZE - i / 2, DX, DY);
2497 ClearRectangle(drawto, DX, DY + DYSIZE - i / 2, DXSIZE, i / 2);
2500 if (door_1.anim_mode == ANIM_HORIZONTAL && x <= DXSIZE)
2502 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
2503 int dst1_x = DX + DXSIZE - i, dst1_y = DY;
2504 int src2_x = DXSIZE - i, src2_y = DOOR_GFX_PAGEY1;
2505 int dst2_x = DX, dst2_y = DY;
2506 int width = i, height = DYSIZE;
2508 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2509 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2512 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2513 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2516 else if (door_1.anim_mode == ANIM_VERTICAL && x <= DYSIZE)
2518 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
2519 int dst1_x = DX, dst1_y = DY + DYSIZE - i;
2520 int src2_x = 0, src2_y = DOOR_GFX_PAGEY1 + DYSIZE - i;
2521 int dst2_x = DX, dst2_y = DY;
2522 int width = DXSIZE, height = i;
2524 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2525 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2528 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2529 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2532 else if (x <= DXSIZE) /* ANIM_DEFAULT */
2534 int j = (door_1.anim_mode == ANIM_DEFAULT ? (DXSIZE - i) / 3 : 0);
2536 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2537 BlitBitmapMasked(bitmap, drawto,
2538 DXSIZE, DOOR_GFX_PAGEY1, i, 77,
2539 DX + DXSIZE - i, DY + j);
2540 BlitBitmapMasked(bitmap, drawto,
2541 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
2542 DX + DXSIZE - i, DY + 140 + j);
2543 SetClipOrigin(bitmap, gc, DX - DXSIZE + i,
2544 DY - (DOOR_GFX_PAGEY1 + j));
2545 BlitBitmapMasked(bitmap, drawto,
2546 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
2548 BlitBitmapMasked(bitmap, drawto,
2549 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
2552 BlitBitmapMasked(bitmap, drawto,
2553 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2555 BlitBitmapMasked(bitmap, drawto,
2556 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2558 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2559 BlitBitmapMasked(bitmap, drawto,
2560 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2561 DX + DXSIZE - i, DY + 77 + j);
2562 BlitBitmapMasked(bitmap, drawto,
2563 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2564 DX + DXSIZE - i, DY + 203 + j);
2567 redraw_mask |= REDRAW_DOOR_1;
2568 door_1_done = (a == end);
2571 if (door_state & DOOR_ACTION_2)
2573 int a = MIN(x * door_2.step_offset, VXSIZE);
2574 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - a : a);
2578 BlitBitmap(bitmap_db_door, drawto,
2579 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i / 2,
2580 VXSIZE, VYSIZE - i / 2, VX, VY);
2582 ClearRectangle(drawto, VX, VY + VYSIZE - i / 2, VXSIZE, i / 2);
2585 if (door_2.anim_mode == ANIM_HORIZONTAL && x <= VXSIZE)
2587 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
2588 int dst1_x = VX + VXSIZE - i, dst1_y = VY;
2589 int src2_x = VXSIZE - i, src2_y = DOOR_GFX_PAGEY2;
2590 int dst2_x = VX, dst2_y = VY;
2591 int width = i, height = VYSIZE;
2593 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2594 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2597 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2598 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2601 else if (door_2.anim_mode == ANIM_VERTICAL && x <= VYSIZE)
2603 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
2604 int dst1_x = VX, dst1_y = VY + VYSIZE - i;
2605 int src2_x = 0, src2_y = DOOR_GFX_PAGEY2 + VYSIZE - i;
2606 int dst2_x = VX, dst2_y = VY;
2607 int width = VXSIZE, height = i;
2609 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2610 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2613 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2614 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2617 else if (x <= VXSIZE) /* ANIM_DEFAULT */
2619 int j = (door_2.anim_mode == ANIM_DEFAULT ? (VXSIZE - i) / 3 : 0);
2621 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2622 BlitBitmapMasked(bitmap, drawto,
2623 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
2624 VX + VXSIZE - i, VY + j);
2625 SetClipOrigin(bitmap, gc,
2626 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2627 BlitBitmapMasked(bitmap, drawto,
2628 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
2631 BlitBitmapMasked(bitmap, drawto,
2632 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2633 i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
2634 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2635 BlitBitmapMasked(bitmap, drawto,
2636 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2638 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2641 redraw_mask |= REDRAW_DOOR_2;
2642 door_2_done = (a == VXSIZE);
2647 if (game_status == GAME_MODE_MAIN)
2650 if (!(door_state & DOOR_NO_DELAY))
2651 WaitUntilDelayReached(&door_delay, door_delay_value);
2655 if (door_state & DOOR_ACTION_1)
2656 door1 = door_state & DOOR_ACTION_1;
2657 if (door_state & DOOR_ACTION_2)
2658 door2 = door_state & DOOR_ACTION_2;
2660 return (door1 | door2);
2663 void DrawSpecialEditorDoor()
2665 /* draw bigger toolbox window */
2666 BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
2667 DOOR_GFX_PAGEX7, 0, EXSIZE + 8, 8,
2669 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2670 EX - 4, VY - 4, EXSIZE + 8, EYSIZE - VYSIZE + 4,
2673 redraw_mask |= REDRAW_ALL;
2676 void UndrawSpecialEditorDoor()
2678 /* draw normal tape recorder window */
2679 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2680 EX - 4, EY - 12, EXSIZE + 8, EYSIZE - VYSIZE + 12,
2683 redraw_mask |= REDRAW_ALL;
2687 /* ---------- new tool button stuff ---------------------------------------- */
2689 /* graphic position values for tool buttons */
2690 #define TOOL_BUTTON_YES_XPOS 2
2691 #define TOOL_BUTTON_YES_YPOS 250
2692 #define TOOL_BUTTON_YES_GFX_YPOS 0
2693 #define TOOL_BUTTON_YES_XSIZE 46
2694 #define TOOL_BUTTON_YES_YSIZE 28
2695 #define TOOL_BUTTON_NO_XPOS 52
2696 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2697 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2698 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2699 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2700 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2701 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2702 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2703 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2704 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2705 #define TOOL_BUTTON_PLAYER_XSIZE 30
2706 #define TOOL_BUTTON_PLAYER_YSIZE 30
2707 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2708 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2709 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2710 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2711 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2712 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2713 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2714 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2715 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2716 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2717 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2718 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2719 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2720 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2721 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2722 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2723 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2724 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2725 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2726 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2735 } toolbutton_info[NUM_TOOL_BUTTONS] =
2738 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2739 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2740 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2745 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2746 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2747 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2752 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2753 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2754 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2755 TOOL_CTRL_ID_CONFIRM,
2759 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2760 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2761 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2762 TOOL_CTRL_ID_PLAYER_1,
2766 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2767 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2768 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2769 TOOL_CTRL_ID_PLAYER_2,
2773 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2774 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2775 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2776 TOOL_CTRL_ID_PLAYER_3,
2780 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2781 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2782 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2783 TOOL_CTRL_ID_PLAYER_4,
2788 void CreateToolButtons()
2792 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2794 Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2795 Bitmap *deco_bitmap = None;
2796 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2797 struct GadgetInfo *gi;
2798 unsigned long event_mask;
2799 int gd_xoffset, gd_yoffset;
2800 int gd_x1, gd_x2, gd_y;
2803 event_mask = GD_EVENT_RELEASED;
2805 gd_xoffset = toolbutton_info[i].xpos;
2806 gd_yoffset = toolbutton_info[i].ypos;
2807 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2808 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2809 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2811 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2813 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
2815 getMiniGraphicSource(PLAYER_NR_GFX(IMG_PLAYER_1, player_nr),
2816 &deco_bitmap, &deco_x, &deco_y);
2817 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2818 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2821 gi = CreateGadget(GDI_CUSTOM_ID, id,
2822 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2823 GDI_X, DX + toolbutton_info[i].x,
2824 GDI_Y, DY + toolbutton_info[i].y,
2825 GDI_WIDTH, toolbutton_info[i].width,
2826 GDI_HEIGHT, toolbutton_info[i].height,
2827 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2828 GDI_STATE, GD_BUTTON_UNPRESSED,
2829 GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
2830 GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
2831 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
2832 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2833 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2834 GDI_DECORATION_SHIFTING, 1, 1,
2835 GDI_EVENT_MASK, event_mask,
2836 GDI_CALLBACK_ACTION, HandleToolButtons,
2840 Error(ERR_EXIT, "cannot create gadget");
2842 tool_gadget[id] = gi;
2846 void FreeToolButtons()
2850 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2851 FreeGadget(tool_gadget[i]);
2854 static void UnmapToolButtons()
2858 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2859 UnmapGadget(tool_gadget[i]);
2862 static void HandleToolButtons(struct GadgetInfo *gi)
2864 request_gadget_id = gi->custom_id;
2867 static struct Mapping_EM_to_RND_object
2870 boolean is_rnd_to_em_mapping; /* unique mapping EM <-> RND */
2871 boolean is_backside; /* backside of moving element */
2877 em_object_mapping_list[] =
2880 Xblank, TRUE, FALSE,
2884 Yacid_splash_eB, FALSE, FALSE,
2885 EL_ACID_SPLASH_RIGHT, -1, -1
2888 Yacid_splash_wB, FALSE, FALSE,
2889 EL_ACID_SPLASH_LEFT, -1, -1
2892 #ifdef EM_ENGINE_BAD_ROLL
2894 Xstone_force_e, FALSE, FALSE,
2895 EL_ROCK, -1, MV_BIT_RIGHT
2898 Xstone_force_w, FALSE, FALSE,
2899 EL_ROCK, -1, MV_BIT_LEFT
2902 Xnut_force_e, FALSE, FALSE,
2903 EL_NUT, -1, MV_BIT_RIGHT
2906 Xnut_force_w, FALSE, FALSE,
2907 EL_NUT, -1, MV_BIT_LEFT
2910 Xspring_force_e, FALSE, FALSE,
2911 EL_SPRING, -1, MV_BIT_RIGHT
2914 Xspring_force_w, FALSE, FALSE,
2915 EL_SPRING, -1, MV_BIT_LEFT
2918 Xemerald_force_e, FALSE, FALSE,
2919 EL_EMERALD, -1, MV_BIT_RIGHT
2922 Xemerald_force_w, FALSE, FALSE,
2923 EL_EMERALD, -1, MV_BIT_LEFT
2926 Xdiamond_force_e, FALSE, FALSE,
2927 EL_DIAMOND, -1, MV_BIT_RIGHT
2930 Xdiamond_force_w, FALSE, FALSE,
2931 EL_DIAMOND, -1, MV_BIT_LEFT
2934 Xbomb_force_e, FALSE, FALSE,
2935 EL_BOMB, -1, MV_BIT_RIGHT
2938 Xbomb_force_w, FALSE, FALSE,
2939 EL_BOMB, -1, MV_BIT_LEFT
2941 #endif /* EM_ENGINE_BAD_ROLL */
2944 Xstone, TRUE, FALSE,
2948 Xstone_pause, FALSE, FALSE,
2952 Xstone_fall, FALSE, FALSE,
2956 Ystone_s, FALSE, FALSE,
2957 EL_ROCK, ACTION_FALLING, -1
2960 Ystone_sB, FALSE, TRUE,
2961 EL_ROCK, ACTION_FALLING, -1
2964 Ystone_e, FALSE, FALSE,
2965 EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT
2968 Ystone_eB, FALSE, TRUE,
2969 EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT
2972 Ystone_w, FALSE, FALSE,
2973 EL_ROCK, ACTION_MOVING, MV_BIT_LEFT
2976 Ystone_wB, FALSE, TRUE,
2977 EL_ROCK, ACTION_MOVING, MV_BIT_LEFT
2984 Xnut_pause, FALSE, FALSE,
2988 Xnut_fall, FALSE, FALSE,
2992 Ynut_s, FALSE, FALSE,
2993 EL_NUT, ACTION_FALLING, -1
2996 Ynut_sB, FALSE, TRUE,
2997 EL_NUT, ACTION_FALLING, -1
3000 Ynut_e, FALSE, FALSE,
3001 EL_NUT, ACTION_MOVING, MV_BIT_RIGHT
3004 Ynut_eB, FALSE, TRUE,
3005 EL_NUT, ACTION_MOVING, MV_BIT_RIGHT
3008 Ynut_w, FALSE, FALSE,
3009 EL_NUT, ACTION_MOVING, MV_BIT_LEFT
3012 Ynut_wB, FALSE, TRUE,
3013 EL_NUT, ACTION_MOVING, MV_BIT_LEFT
3016 Xbug_n, TRUE, FALSE,
3020 Xbug_e, TRUE, FALSE,
3021 EL_BUG_RIGHT, -1, -1
3024 Xbug_s, TRUE, FALSE,
3028 Xbug_w, TRUE, FALSE,
3032 Xbug_gon, FALSE, FALSE,
3036 Xbug_goe, FALSE, FALSE,
3037 EL_BUG_RIGHT, -1, -1
3040 Xbug_gos, FALSE, FALSE,
3044 Xbug_gow, FALSE, FALSE,
3048 Ybug_n, FALSE, FALSE,
3049 EL_BUG, ACTION_MOVING, MV_BIT_UP
3052 Ybug_nB, FALSE, TRUE,
3053 EL_BUG, ACTION_MOVING, MV_BIT_UP
3056 Ybug_e, FALSE, FALSE,
3057 EL_BUG, ACTION_MOVING, MV_BIT_RIGHT
3060 Ybug_eB, FALSE, TRUE,
3061 EL_BUG, ACTION_MOVING, MV_BIT_RIGHT
3064 Ybug_s, FALSE, FALSE,
3065 EL_BUG, ACTION_MOVING, MV_BIT_DOWN
3068 Ybug_sB, FALSE, TRUE,
3069 EL_BUG, ACTION_MOVING, MV_BIT_DOWN
3072 Ybug_w, FALSE, FALSE,
3073 EL_BUG, ACTION_MOVING, MV_BIT_LEFT
3076 Ybug_wB, FALSE, TRUE,
3077 EL_BUG, ACTION_MOVING, MV_BIT_LEFT
3080 Ybug_w_n, FALSE, FALSE,
3081 EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_UP
3084 Ybug_n_e, FALSE, FALSE,
3085 EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3088 Ybug_e_s, FALSE, FALSE,
3089 EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
3092 Ybug_s_w, FALSE, FALSE,
3093 EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3096 Ybug_e_n, FALSE, FALSE,
3097 EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
3100 Ybug_s_e, FALSE, FALSE,
3101 EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3104 Ybug_w_s, FALSE, FALSE,
3105 EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
3108 Ybug_n_w, FALSE, FALSE,
3109 EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3112 Ybug_stone, FALSE, FALSE,
3113 EL_BUG, ACTION_SMASHED_BY_ROCK, -1
3116 Ybug_spring, FALSE, FALSE,
3117 EL_BUG, ACTION_SMASHED_BY_SPRING, -1
3120 Xtank_n, TRUE, FALSE,
3121 EL_SPACESHIP_UP, -1, -1
3124 Xtank_e, TRUE, FALSE,
3125 EL_SPACESHIP_RIGHT, -1, -1
3128 Xtank_s, TRUE, FALSE,
3129 EL_SPACESHIP_DOWN, -1, -1
3132 Xtank_w, TRUE, FALSE,
3133 EL_SPACESHIP_LEFT, -1, -1
3136 Xtank_gon, FALSE, FALSE,
3137 EL_SPACESHIP_UP, -1, -1
3140 Xtank_goe, FALSE, FALSE,
3141 EL_SPACESHIP_RIGHT, -1, -1
3144 Xtank_gos, FALSE, FALSE,
3145 EL_SPACESHIP_DOWN, -1, -1
3148 Xtank_gow, FALSE, FALSE,
3149 EL_SPACESHIP_LEFT, -1, -1
3152 Ytank_n, FALSE, FALSE,
3153 EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP
3156 Ytank_nB, FALSE, TRUE,
3157 EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP
3160 Ytank_e, FALSE, FALSE,
3161 EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT
3164 Ytank_eB, FALSE, TRUE,
3165 EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT
3168 Ytank_s, FALSE, FALSE,
3169 EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN
3172 Ytank_sB, FALSE, TRUE,
3173 EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN
3176 Ytank_w, FALSE, FALSE,
3177 EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT
3180 Ytank_wB, FALSE, TRUE,
3181 EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT
3184 Ytank_w_n, FALSE, FALSE,
3185 EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_UP
3188 Ytank_n_e, FALSE, FALSE,
3189 EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3192 Ytank_e_s, FALSE, FALSE,
3193 EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
3196 Ytank_s_w, FALSE, FALSE,
3197 EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3200 Ytank_e_n, FALSE, FALSE,
3201 EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
3204 Ytank_s_e, FALSE, FALSE,
3205 EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3208 Ytank_w_s, FALSE, FALSE,
3209 EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
3212 Ytank_n_w, FALSE, FALSE,
3213 EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3216 Ytank_stone, FALSE, FALSE,
3217 EL_SPACESHIP, ACTION_SMASHED_BY_ROCK, -1
3220 Ytank_spring, FALSE, FALSE,
3221 EL_SPACESHIP, ACTION_SMASHED_BY_SPRING, -1
3224 Xandroid, TRUE, FALSE,
3225 EL_EMC_ANDROID, ACTION_ACTIVE, -1
3228 Xandroid_1_n, FALSE, FALSE,
3229 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_UP
3232 Xandroid_2_n, FALSE, FALSE,
3233 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_UP
3236 Xandroid_1_e, FALSE, FALSE,
3237 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_RIGHT
3240 Xandroid_2_e, FALSE, FALSE,
3241 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_RIGHT
3244 Xandroid_1_w, FALSE, FALSE,
3245 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_LEFT
3248 Xandroid_2_w, FALSE, FALSE,
3249 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_LEFT
3252 Xandroid_1_s, FALSE, FALSE,
3253 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_DOWN
3256 Xandroid_2_s, FALSE, FALSE,
3257 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_DOWN
3260 Yandroid_n, FALSE, FALSE,
3261 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_UP
3264 Yandroid_nB, FALSE, TRUE,
3265 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_UP
3268 Yandroid_ne, FALSE, FALSE,
3269 EL_EMC_ANDROID, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3272 Yandroid_neB, FALSE, TRUE,
3273 EL_EMC_ANDROID, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3276 Yandroid_e, FALSE, FALSE,
3277 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_RIGHT
3280 Yandroid_eB, FALSE, TRUE,
3281 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_RIGHT
3284 Yandroid_se, FALSE, FALSE,
3285 EL_EMC_ANDROID, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3288 Yandroid_seB, FALSE, TRUE,
3289 EL_EMC_ANDROID, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3292 Yandroid_s, FALSE, FALSE,
3293 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_DOWN
3296 Yandroid_sB, FALSE, TRUE,
3297 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_DOWN
3300 Yandroid_sw, FALSE, FALSE,
3301 EL_EMC_ANDROID, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3304 Yandroid_swB, FALSE, TRUE,
3305 EL_EMC_ANDROID, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3308 Yandroid_w, FALSE, FALSE,
3309 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_LEFT
3312 Yandroid_wB, FALSE, TRUE,
3313 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_LEFT
3316 Yandroid_nw, FALSE, FALSE,
3317 EL_EMC_ANDROID, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3320 Yandroid_nwB, FALSE, TRUE,
3321 EL_EMC_ANDROID, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3324 Xspring, TRUE, FALSE,
3328 Xspring_pause, FALSE, FALSE,
3332 Xspring_e, FALSE, FALSE,
3336 Xspring_w, FALSE, FALSE,
3340 Xspring_fall, FALSE, FALSE,
3344 Yspring_s, FALSE, FALSE,
3345 EL_SPRING, ACTION_FALLING, -1
3348 Yspring_sB, FALSE, TRUE,
3349 EL_SPRING, ACTION_FALLING, -1
3352 Yspring_e, FALSE, FALSE,
3353 EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT
3356 Yspring_eB, FALSE, TRUE,
3357 EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT
3360 Yspring_w, FALSE, FALSE,
3361 EL_SPRING, ACTION_MOVING, MV_BIT_LEFT
3364 Yspring_wB, FALSE, TRUE,
3365 EL_SPRING, ACTION_MOVING, MV_BIT_LEFT
3368 Yspring_kill_e, FALSE, FALSE,
3369 EL_ROBOT, ACTION_SLURPED_BY_SPRING, MV_BIT_RIGHT
3372 Yspring_kill_eB, FALSE, TRUE,
3373 EL_ROBOT, ACTION_SLURPED_BY_SPRING, MV_BIT_RIGHT
3376 Yspring_kill_w, FALSE, FALSE,
3377 EL_ROBOT, ACTION_SLURPED_BY_SPRING, MV_BIT_LEFT
3380 Yspring_kill_wB, FALSE, TRUE,
3381 EL_ROBOT, ACTION_SLURPED_BY_SPRING, MV_BIT_LEFT
3384 Xeater_n, TRUE, FALSE,
3388 Xeater_e, FALSE, FALSE,
3392 Xeater_w, FALSE, FALSE,
3396 Xeater_s, FALSE, FALSE,
3400 Yeater_n, FALSE, FALSE,
3401 EL_YAMYAM, ACTION_MOVING, MV_BIT_UP
3404 Yeater_nB, FALSE, TRUE,
3405 EL_YAMYAM, ACTION_MOVING, MV_BIT_UP
3408 Yeater_e, FALSE, FALSE,
3409 EL_YAMYAM, ACTION_MOVING, MV_BIT_RIGHT
3412 Yeater_eB, FALSE, TRUE,
3413 EL_YAMYAM, ACTION_MOVING, MV_BIT_RIGHT
3416 Yeater_s, FALSE, FALSE,
3417 EL_YAMYAM, ACTION_MOVING, MV_BIT_DOWN
3420 Yeater_sB, FALSE, TRUE,
3421 EL_YAMYAM, ACTION_MOVING, MV_BIT_DOWN
3424 Yeater_w, FALSE, FALSE,
3425 EL_YAMYAM, ACTION_MOVING, MV_BIT_LEFT
3428 Yeater_wB, FALSE, TRUE,
3429 EL_YAMYAM, ACTION_MOVING, MV_BIT_LEFT
3432 Yeater_stone, FALSE, FALSE,
3433 EL_YAMYAM, ACTION_SMASHED_BY_ROCK, -1
3436 Yeater_spring, FALSE, FALSE,
3437 EL_YAMYAM, ACTION_SMASHED_BY_SPRING, -1
3440 Xalien, TRUE, FALSE,
3444 Xalien_pause, FALSE, FALSE,
3448 Yalien_n, FALSE, FALSE,
3449 EL_ROBOT, ACTION_MOVING, MV_BIT_UP
3452 Yalien_nB, FALSE, TRUE,
3453 EL_ROBOT, ACTION_MOVING, MV_BIT_UP
3456 Yalien_e, FALSE, FALSE,
3457 EL_ROBOT, ACTION_MOVING, MV_BIT_RIGHT
3460 Yalien_eB, FALSE, TRUE,
3461 EL_ROBOT, ACTION_MOVING, MV_BIT_RIGHT
3464 Yalien_s, FALSE, FALSE,
3465 EL_ROBOT, ACTION_MOVING, MV_BIT_DOWN
3468 Yalien_sB, FALSE, TRUE,
3469 EL_ROBOT, ACTION_MOVING, MV_BIT_DOWN
3472 Yalien_w, FALSE, FALSE,
3473 EL_ROBOT, ACTION_MOVING, MV_BIT_LEFT
3476 Yalien_wB, FALSE, TRUE,
3477 EL_ROBOT, ACTION_MOVING, MV_BIT_LEFT
3480 Yalien_stone, FALSE, FALSE,
3481 EL_ROBOT, ACTION_SMASHED_BY_ROCK, -1
3484 Yalien_spring, FALSE, FALSE,
3485 EL_ROBOT, ACTION_SMASHED_BY_SPRING, -1
3488 Xemerald, TRUE, FALSE,
3492 Xemerald_pause, FALSE, FALSE,
3496 Xemerald_fall, FALSE, FALSE,
3500 Xemerald_shine, FALSE, FALSE,
3501 EL_EMERALD, ACTION_TWINKLING, -1
3504 Yemerald_s, FALSE, FALSE,
3505 EL_EMERALD, ACTION_FALLING, -1
3508 Yemerald_sB, FALSE, TRUE,
3509 EL_EMERALD, ACTION_FALLING, -1
3512 Yemerald_e, FALSE, FALSE,
3513 EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT
3516 Yemerald_eB, FALSE, TRUE,
3517 EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT
3520 Yemerald_w, FALSE, FALSE,
3521 EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT
3524 Yemerald_wB, FALSE, TRUE,
3525 EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT
3528 Yemerald_eat, FALSE, FALSE,
3529 EL_EMERALD, ACTION_COLLECTING, -1
3532 Yemerald_stone, FALSE, FALSE,
3533 EL_NUT, ACTION_BREAKING, -1
3536 Xdiamond, TRUE, FALSE,
3540 Xdiamond_pause, FALSE, FALSE,
3544 Xdiamond_fall, FALSE, FALSE,
3548 Xdiamond_shine, FALSE, FALSE,
3549 EL_DIAMOND, ACTION_TWINKLING, -1
3552 Ydiamond_s, FALSE, FALSE,
3553 EL_DIAMOND, ACTION_FALLING, -1
3556 Ydiamond_sB, FALSE, TRUE,
3557 EL_DIAMOND, ACTION_FALLING, -1
3560 Ydiamond_e, FALSE, FALSE,
3561 EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT
3564 Ydiamond_eB, FALSE, TRUE,
3565 EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT
3568 Ydiamond_w, FALSE, FALSE,
3569 EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT
3572 Ydiamond_wB, FALSE, TRUE,
3573 EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT
3576 Ydiamond_eat, FALSE, FALSE,
3577 EL_DIAMOND, ACTION_COLLECTING, -1
3580 Ydiamond_stone, FALSE, FALSE,
3581 EL_DIAMOND, ACTION_SMASHED_BY_ROCK, -1
3584 Xdrip_fall, TRUE, FALSE,
3585 EL_AMOEBA_DROP, -1, -1
3588 Xdrip_stretch, FALSE, FALSE,
3589 EL_AMOEBA_DROP, ACTION_FALLING, -1
3592 Xdrip_stretchB, FALSE, TRUE,
3593 EL_AMOEBA_DROP, ACTION_FALLING, -1
3596 Xdrip_eat, FALSE, FALSE,
3597 EL_AMOEBA_DROP, ACTION_GROWING, -1
3600 Ydrip_s1, FALSE, FALSE,
3601 EL_AMOEBA_DROP, ACTION_FALLING, -1
3604 Ydrip_s1B, FALSE, TRUE,
3605 EL_AMOEBA_DROP, ACTION_FALLING, -1
3608 Ydrip_s2, FALSE, FALSE,
3609 EL_AMOEBA_DROP, ACTION_FALLING, -1
3612 Ydrip_s2B, FALSE, TRUE,
3613 EL_AMOEBA_DROP, ACTION_FALLING, -1
3620 Xbomb_pause, FALSE, FALSE,
3624 Xbomb_fall, FALSE, FALSE,
3628 Ybomb_s, FALSE, FALSE,
3629 EL_BOMB, ACTION_FALLING, -1
3632 Ybomb_sB, FALSE, TRUE,
3633 EL_BOMB, ACTION_FALLING, -1
3636 Ybomb_e, FALSE, FALSE,
3637 EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT
3640 Ybomb_eB, FALSE, TRUE,
3641 EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT
3644 Ybomb_w, FALSE, FALSE,
3645 EL_BOMB, ACTION_MOVING, MV_BIT_LEFT
3648 Ybomb_wB, FALSE, TRUE,
3649 EL_BOMB, ACTION_MOVING, MV_BIT_LEFT
3652 Ybomb_eat, FALSE, FALSE,
3653 EL_BOMB, ACTION_ACTIVATING, -1
3656 Xballoon, TRUE, FALSE,
3660 Yballoon_n, FALSE, FALSE,
3661 EL_BALLOON, ACTION_MOVING, MV_BIT_UP
3664 Yballoon_nB, FALSE, TRUE,
3665 EL_BALLOON, ACTION_MOVING, MV_BIT_UP
3668 Yballoon_e, FALSE, FALSE,
3669 EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT
3672 Yballoon_eB, FALSE, TRUE,
3673 EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT
3676 Yballoon_s, FALSE, FALSE,
3677 EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN
3680 Yballoon_sB, FALSE, TRUE,
3681 EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN
3684 Yballoon_w, FALSE, FALSE,
3685 EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT
3688 Yballoon_wB, FALSE, TRUE,
3689 EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT
3692 Xgrass, TRUE, FALSE,
3693 EL_EMC_GRASS, -1, -1
3696 Ygrass_nB, FALSE, FALSE,
3697 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_UP
3700 Ygrass_eB, FALSE, FALSE,
3701 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_RIGHT
3704 Ygrass_sB, FALSE, FALSE,
3705 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_DOWN
3708 Ygrass_wB, FALSE, FALSE,
3709 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_LEFT
3716 Ydirt_nB, FALSE, FALSE,
3717 EL_SAND, ACTION_DIGGING, MV_BIT_UP
3720 Ydirt_eB, FALSE, FALSE,
3721 EL_SAND, ACTION_DIGGING, MV_BIT_RIGHT
3724 Ydirt_sB, FALSE, FALSE,
3725 EL_SAND, ACTION_DIGGING, MV_BIT_DOWN
3728 Ydirt_wB, FALSE, FALSE,
3729 EL_SAND, ACTION_DIGGING, MV_BIT_LEFT
3732 Xacid_ne, TRUE, FALSE,
3733 EL_ACID_POOL_TOPRIGHT, -1, -1
3736 Xacid_se, TRUE, FALSE,
3737 EL_ACID_POOL_BOTTOMRIGHT, -1, -1
3740 Xacid_s, TRUE, FALSE,
3741 EL_ACID_POOL_BOTTOM, -1, -1
3744 Xacid_sw, TRUE, FALSE,
3745 EL_ACID_POOL_BOTTOMLEFT, -1, -1
3748 Xacid_nw, TRUE, FALSE,
3749 EL_ACID_POOL_TOPLEFT, -1, -1
3752 Xacid_1, TRUE, FALSE,
3756 Xacid_2, FALSE, FALSE,
3760 Xacid_3, FALSE, FALSE,
3764 Xacid_4, FALSE, FALSE,
3768 Xacid_5, FALSE, FALSE,
3772 Xacid_6, FALSE, FALSE,
3776 Xacid_7, FALSE, FALSE,
3780 Xacid_8, FALSE, FALSE,
3784 Xball_1, TRUE, FALSE,
3785 EL_EMC_MAGIC_BALL, -1, -1
3788 Xball_1B, FALSE, FALSE,
3789 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
3792 Xball_2, FALSE, FALSE,
3793 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
3796 Xball_2B, FALSE, FALSE,
3797 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
3800 Yball_eat, FALSE, FALSE,
3801 EL_EMC_MAGIC_BALL, ACTION_DROPPING, -1
3804 Ykey_1_eat, FALSE, FALSE,
3805 EL_EM_KEY_1, ACTION_COLLECTING, -1
3808 Ykey_2_eat, FALSE, FALSE,
3809 EL_EM_KEY_2, ACTION_COLLECTING, -1
3812 Ykey_3_eat, FALSE, FALSE,
3813 EL_EM_KEY_3, ACTION_COLLECTING, -1
3816 Ykey_4_eat, FALSE, FALSE,
3817 EL_EM_KEY_4, ACTION_COLLECTING, -1
3820 Ykey_5_eat, FALSE, FALSE,
3821 EL_EMC_KEY_5, ACTION_COLLECTING, -1
3824 Ykey_6_eat, FALSE, FALSE,
3825 EL_EMC_KEY_6, ACTION_COLLECTING, -1
3828 Ykey_7_eat, FALSE, FALSE,
3829 EL_EMC_KEY_7, ACTION_COLLECTING, -1
3832 Ykey_8_eat, FALSE, FALSE,
3833 EL_EMC_KEY_8, ACTION_COLLECTING, -1
3836 Ylenses_eat, FALSE, FALSE,
3837 EL_EMC_LENSES, ACTION_COLLECTING, -1
3840 Ymagnify_eat, FALSE, FALSE,
3841 EL_EMC_MAGNIFIER, ACTION_COLLECTING, -1
3844 Ygrass_eat, FALSE, FALSE,
3845 EL_EMC_GRASS, ACTION_SNAPPING, -1
3848 Ydirt_eat, FALSE, FALSE,
3849 EL_SAND, ACTION_SNAPPING, -1
3852 Xgrow_ns, TRUE, FALSE,
3853 EL_EXPANDABLE_WALL_VERTICAL, -1, -1
3856 Ygrow_ns_eat, FALSE, FALSE,
3857 EL_EXPANDABLE_WALL_VERTICAL, ACTION_GROWING, -1
3860 Xgrow_ew, TRUE, FALSE,
3861 EL_EXPANDABLE_WALL_HORIZONTAL, -1, -1
3864 Ygrow_ew_eat, FALSE, FALSE,
3865 EL_EXPANDABLE_WALL_HORIZONTAL, ACTION_GROWING, -1
3868 Xwonderwall, TRUE, FALSE,
3869 EL_MAGIC_WALL, -1, -1
3872 XwonderwallB, FALSE, FALSE,
3873 EL_MAGIC_WALL, ACTION_ACTIVE, -1
3876 Xamoeba_1, TRUE, FALSE,
3877 EL_AMOEBA_DRY, ACTION_OTHER, -1
3880 Xamoeba_2, FALSE, FALSE,
3881 EL_AMOEBA_DRY, ACTION_OTHER, -1
3884 Xamoeba_3, FALSE, FALSE,
3885 EL_AMOEBA_DRY, ACTION_OTHER, -1
3888 Xamoeba_4, FALSE, FALSE,
3889 EL_AMOEBA_DRY, ACTION_OTHER, -1
3892 Xamoeba_5, TRUE, FALSE,
3893 EL_AMOEBA_WET, ACTION_OTHER, -1
3896 Xamoeba_6, FALSE, FALSE,
3897 EL_AMOEBA_WET, ACTION_OTHER, -1
3900 Xamoeba_7, FALSE, FALSE,
3901 EL_AMOEBA_WET, ACTION_OTHER, -1
3904 Xamoeba_8, FALSE, FALSE,
3905 EL_AMOEBA_WET, ACTION_OTHER, -1
3908 Xdoor_1, TRUE, FALSE,
3909 EL_EM_GATE_1, -1, -1
3912 Xdoor_2, TRUE, FALSE,
3913 EL_EM_GATE_2, -1, -1
3916 Xdoor_3, TRUE, FALSE,
3917 EL_EM_GATE_3, -1, -1
3920 Xdoor_4, TRUE, FALSE,
3921 EL_EM_GATE_4, -1, -1
3924 Xdoor_5, TRUE, FALSE,
3925 EL_EMC_GATE_5, -1, -1
3928 Xdoor_6, TRUE, FALSE,
3929 EL_EMC_GATE_6, -1, -1
3932 Xdoor_7, TRUE, FALSE,
3933 EL_EMC_GATE_7, -1, -1
3936 Xdoor_8, TRUE, FALSE,
3937 EL_EMC_GATE_8, -1, -1
3940 Xkey_1, TRUE, FALSE,
3944 Xkey_2, TRUE, FALSE,
3948 Xkey_3, TRUE, FALSE,
3952 Xkey_4, TRUE, FALSE,
3956 Xkey_5, TRUE, FALSE,
3957 EL_EMC_KEY_5, -1, -1
3960 Xkey_6, TRUE, FALSE,
3961 EL_EMC_KEY_6, -1, -1
3964 Xkey_7, TRUE, FALSE,
3965 EL_EMC_KEY_7, -1, -1
3968 Xkey_8, TRUE, FALSE,
3969 EL_EMC_KEY_8, -1, -1
3972 Xwind_n, TRUE, FALSE,
3973 EL_BALLOON_SWITCH_UP, -1, -1
3976 Xwind_e, TRUE, FALSE,
3977 EL_BALLOON_SWITCH_RIGHT, -1, -1
3980 Xwind_s, TRUE, FALSE,
3981 EL_BALLOON_SWITCH_DOWN, -1, -1
3984 Xwind_w, TRUE, FALSE,
3985 EL_BALLOON_SWITCH_LEFT, -1, -1
3988 Xwind_nesw, TRUE, FALSE,
3989 EL_BALLOON_SWITCH_ANY, -1, -1
3992 Xwind_stop, TRUE, FALSE,
3993 EL_BALLOON_SWITCH_NONE, -1, -1
3997 EL_EXIT_CLOSED, -1, -1
4000 Xexit_1, TRUE, FALSE,
4001 EL_EXIT_OPEN, -1, -1
4004 Xexit_2, FALSE, FALSE,
4005 EL_EXIT_OPEN, -1, -1
4008 Xexit_3, FALSE, FALSE,
4009 EL_EXIT_OPEN, -1, -1
4012 Xdynamite, TRUE, FALSE,
4016 Ydynamite_eat, FALSE, FALSE,
4017 EL_DYNAMITE, ACTION_COLLECTING, -1
4020 Xdynamite_1, TRUE, FALSE,
4021 EL_DYNAMITE_ACTIVE, -1, -1
4024 Xdynamite_2, FALSE, FALSE,
4025 EL_DYNAMITE_ACTIVE, -1, -1
4028 Xdynamite_3, FALSE, FALSE,
4029 EL_DYNAMITE_ACTIVE, -1, -1
4032 Xdynamite_4, FALSE, FALSE,
4033 EL_DYNAMITE_ACTIVE, -1, -1
4036 Xbumper, TRUE, FALSE,
4037 EL_EMC_SPRING_BUMPER, -1, -1
4040 XbumperB, FALSE, FALSE,
4041 EL_EMC_SPRING_BUMPER, ACTION_ACTIVE, -1
4044 Xwheel, TRUE, FALSE,
4045 EL_ROBOT_WHEEL, -1, -1
4048 XwheelB, FALSE, FALSE,
4049 EL_ROBOT_WHEEL, ACTION_ACTIVE, -1
4052 Xswitch, TRUE, FALSE,
4053 EL_EMC_MAGIC_BALL_SWITCH, -1, -1
4056 XswitchB, FALSE, FALSE,
4057 EL_EMC_MAGIC_BALL_SWITCH, ACTION_ACTIVE, -1
4061 EL_QUICKSAND_EMPTY, -1, -1
4064 Xsand_stone, TRUE, FALSE,
4065 EL_QUICKSAND_FULL, -1, -1
4068 Xsand_stonein_1, FALSE, FALSE,
4069 EL_ROCK, ACTION_FILLING, -1
4072 Xsand_stonein_2, FALSE, FALSE,
4073 EL_ROCK, ACTION_FILLING, -1
4076 Xsand_stonein_3, FALSE, FALSE,
4077 EL_ROCK, ACTION_FILLING, -1
4080 Xsand_stonein_4, FALSE, FALSE,
4081 EL_ROCK, ACTION_FILLING, -1
4084 Xsand_stonesand_1, FALSE, FALSE,
4085 EL_QUICKSAND_FULL, -1, -1
4088 Xsand_stonesand_2, FALSE, FALSE,
4089 EL_QUICKSAND_FULL, -1, -1
4092 Xsand_stonesand_3, FALSE, FALSE,
4093 EL_QUICKSAND_FULL, -1, -1
4096 Xsand_stonesand_4, FALSE, FALSE,
4097 EL_QUICKSAND_FULL, -1, -1
4100 Xsand_stoneout_1, FALSE, FALSE,
4101 EL_ROCK, ACTION_EMPTYING, -1
4104 Xsand_stoneout_2, FALSE, FALSE,
4105 EL_ROCK, ACTION_EMPTYING, -1
4108 Xsand_sandstone_1, FALSE, FALSE,
4109 EL_QUICKSAND_FULL, -1, -1
4112 Xsand_sandstone_2, FALSE, FALSE,
4113 EL_QUICKSAND_FULL, -1, -1
4116 Xsand_sandstone_3, FALSE, FALSE,
4117 EL_QUICKSAND_FULL, -1, -1
4120 Xsand_sandstone_4, FALSE, FALSE,
4121 EL_QUICKSAND_FULL, -1, -1
4124 Xplant, TRUE, FALSE,
4125 EL_EMC_PLANT, -1, -1
4128 Yplant, FALSE, FALSE,
4129 EL_EMC_PLANT, -1, -1
4132 Xlenses, TRUE, FALSE,
4133 EL_EMC_LENSES, -1, -1
4136 Xmagnify, TRUE, FALSE,
4137 EL_EMC_MAGNIFIER, -1, -1
4140 Xdripper, TRUE, FALSE,
4141 EL_EMC_DRIPPER, -1, -1
4144 XdripperB, FALSE, FALSE,
4145 EL_EMC_DRIPPER, ACTION_ACTIVE, -1
4148 Xfake_blank, TRUE, FALSE,
4149 EL_INVISIBLE_WALL, -1, -1
4152 Xfake_blankB, FALSE, FALSE,
4153 EL_INVISIBLE_WALL, ACTION_ACTIVE, -1
4156 Xfake_grass, TRUE, FALSE,
4157 EL_EMC_FAKE_GRASS, -1, -1
4160 Xfake_grassB, FALSE, FALSE,
4161 EL_EMC_FAKE_GRASS, ACTION_ACTIVE, -1
4164 Xfake_door_1, TRUE, FALSE,
4165 EL_EM_GATE_1_GRAY, -1, -1
4168 Xfake_door_2, TRUE, FALSE,
4169 EL_EM_GATE_2_GRAY, -1, -1
4172 Xfake_door_3, TRUE, FALSE,
4173 EL_EM_GATE_3_GRAY, -1, -1
4176 Xfake_door_4, TRUE, FALSE,
4177 EL_EM_GATE_4_GRAY, -1, -1
4180 Xfake_door_5, TRUE, FALSE,
4181 EL_EMC_GATE_5_GRAY, -1, -1
4184 Xfake_door_6, TRUE, FALSE,
4185 EL_EMC_GATE_6_GRAY, -1, -1
4188 Xfake_door_7, TRUE, FALSE,
4189 EL_EMC_GATE_7_GRAY, -1, -1
4192 Xfake_door_8, TRUE, FALSE,
4193 EL_EMC_GATE_8_GRAY, -1, -1
4196 Xfake_acid_1, TRUE, FALSE,
4197 EL_EMC_FAKE_ACID, -1, -1
4200 Xfake_acid_2, FALSE, FALSE,
4201 EL_EMC_FAKE_ACID, -1, -1
4204 Xfake_acid_3, FALSE, FALSE,
4205 EL_EMC_FAKE_ACID, -1, -1
4208 Xfake_acid_4, FALSE, FALSE,
4209 EL_EMC_FAKE_ACID, -1, -1
4212 Xfake_acid_5, FALSE, FALSE,
4213 EL_EMC_FAKE_ACID, -1, -1
4216 Xfake_acid_6, FALSE, FALSE,
4217 EL_EMC_FAKE_ACID, -1, -1
4220 Xfake_acid_7, FALSE, FALSE,
4221 EL_EMC_FAKE_ACID, -1, -1
4224 Xfake_acid_8, FALSE, FALSE,
4225 EL_EMC_FAKE_ACID, -1, -1
4228 Xsteel_1, TRUE, FALSE,
4229 EL_STEELWALL, -1, -1
4232 Xsteel_2, TRUE, FALSE,
4233 EL_EMC_STEELWALL_2, -1, -1
4236 Xsteel_3, TRUE, FALSE,
4237 EL_EMC_STEELWALL_3, -1, -1
4240 Xsteel_4, TRUE, FALSE,
4241 EL_EMC_STEELWALL_4, -1, -1
4244 Xwall_1, TRUE, FALSE,
4248 Xwall_2, TRUE, FALSE,
4249 EL_EMC_WALL_14, -1, -1
4252 Xwall_3, TRUE, FALSE,
4253 EL_EMC_WALL_15, -1, -1
4256 Xwall_4, TRUE, FALSE,
4257 EL_EMC_WALL_16, -1, -1
4260 Xround_wall_1, TRUE, FALSE,
4261 EL_WALL_SLIPPERY, -1, -1
4264 Xround_wall_2, TRUE, FALSE,
4265 EL_EMC_WALL_SLIPPERY_2, -1, -1
4268 Xround_wall_3, TRUE, FALSE,
4269 EL_EMC_WALL_SLIPPERY_3, -1, -1
4272 Xround_wall_4, TRUE, FALSE,
4273 EL_EMC_WALL_SLIPPERY_4, -1, -1
4276 Xdecor_1, TRUE, FALSE,
4277 EL_EMC_WALL_8, -1, -1
4280 Xdecor_2, TRUE, FALSE,
4281 EL_EMC_WALL_6, -1, -1
4284 Xdecor_3, TRUE, FALSE,
4285 EL_EMC_WALL_4, -1, -1
4288 Xdecor_4, TRUE, FALSE,
4289 EL_EMC_WALL_7, -1, -1
4292 Xdecor_5, TRUE, FALSE,
4293 EL_EMC_WALL_5, -1, -1
4296 Xdecor_6, TRUE, FALSE,
4297 EL_EMC_WALL_9, -1, -1
4300 Xdecor_7, TRUE, FALSE,
4301 EL_EMC_WALL_10, -1, -1
4304 Xdecor_8, TRUE, FALSE,
4305 EL_EMC_WALL_1, -1, -1
4308 Xdecor_9, TRUE, FALSE,
4309 EL_EMC_WALL_2, -1, -1
4312 Xdecor_10, TRUE, FALSE,
4313 EL_EMC_WALL_3, -1, -1
4316 Xdecor_11, TRUE, FALSE,
4317 EL_EMC_WALL_11, -1, -1
4320 Xdecor_12, TRUE, FALSE,
4321 EL_EMC_WALL_12, -1, -1
4324 Xalpha_0, TRUE, FALSE,
4325 EL_CHAR('0'), -1, -1
4328 Xalpha_1, TRUE, FALSE,
4329 EL_CHAR('1'), -1, -1
4332 Xalpha_2, TRUE, FALSE,
4333 EL_CHAR('2'), -1, -1
4336 Xalpha_3, TRUE, FALSE,
4337 EL_CHAR('3'), -1, -1
4340 Xalpha_4, TRUE, FALSE,
4341 EL_CHAR('4'), -1, -1
4344 Xalpha_5, TRUE, FALSE,
4345 EL_CHAR('5'), -1, -1
4348 Xalpha_6, TRUE, FALSE,
4349 EL_CHAR('6'), -1, -1
4352 Xalpha_7, TRUE, FALSE,
4353 EL_CHAR('7'), -1, -1
4356 Xalpha_8, TRUE, FALSE,
4357 EL_CHAR('8'), -1, -1
4360 Xalpha_9, TRUE, FALSE,
4361 EL_CHAR('9'), -1, -1
4364 Xalpha_excla, TRUE, FALSE,
4365 EL_CHAR('!'), -1, -1
4368 Xalpha_quote, TRUE, FALSE,
4369 EL_CHAR('"'), -1, -1
4372 Xalpha_comma, TRUE, FALSE,
4373 EL_CHAR(','), -1, -1
4376 Xalpha_minus, TRUE, FALSE,
4377 EL_CHAR('-'), -1, -1
4380 Xalpha_perio, TRUE, FALSE,
4381 EL_CHAR('.'), -1, -1
4384 Xalpha_colon, TRUE, FALSE,
4385 EL_CHAR(':'), -1, -1
4388 Xalpha_quest, TRUE, FALSE,
4389 EL_CHAR('?'), -1, -1
4392 Xalpha_a, TRUE, FALSE,
4393 EL_CHAR('A'), -1, -1
4396 Xalpha_b, TRUE, FALSE,
4397 EL_CHAR('B'), -1, -1
4400 Xalpha_c, TRUE, FALSE,
4401 EL_CHAR('C'), -1, -1
4404 Xalpha_d, TRUE, FALSE,
4405 EL_CHAR('D'), -1, -1
4408 Xalpha_e, TRUE, FALSE,
4409 EL_CHAR('E'), -1, -1
4412 Xalpha_f, TRUE, FALSE,
4413 EL_CHAR('F'), -1, -1
4416 Xalpha_g, TRUE, FALSE,
4417 EL_CHAR('G'), -1, -1
4420 Xalpha_h, TRUE, FALSE,
4421 EL_CHAR('H'), -1, -1
4424 Xalpha_i, TRUE, FALSE,
4425 EL_CHAR('I'), -1, -1
4428 Xalpha_j, TRUE, FALSE,
4429 EL_CHAR('J'), -1, -1
4432 Xalpha_k, TRUE, FALSE,
4433 EL_CHAR('K'), -1, -1
4436 Xalpha_l, TRUE, FALSE,
4437 EL_CHAR('L'), -1, -1
4440 Xalpha_m, TRUE, FALSE,
4441 EL_CHAR('M'), -1, -1
4444 Xalpha_n, TRUE, FALSE,
4445 EL_CHAR('N'), -1, -1
4448 Xalpha_o, TRUE, FALSE,
4449 EL_CHAR('O'), -1, -1
4452 Xalpha_p, TRUE, FALSE,
4453 EL_CHAR('P'), -1, -1
4456 Xalpha_q, TRUE, FALSE,
4457 EL_CHAR('Q'), -1, -1
4460 Xalpha_r, TRUE, FALSE,
4461 EL_CHAR('R'), -1, -1
4464 Xalpha_s, TRUE, FALSE,
4465 EL_CHAR('S'), -1, -1
4468 Xalpha_t, TRUE, FALSE,
4469 EL_CHAR('T'), -1, -1
4472 Xalpha_u, TRUE, FALSE,
4473 EL_CHAR('U'), -1, -1
4476 Xalpha_v, TRUE, FALSE,
4477 EL_CHAR('V'), -1, -1
4480 Xalpha_w, TRUE, FALSE,
4481 EL_CHAR('W'), -1, -1
4484 Xalpha_x, TRUE, FALSE,
4485 EL_CHAR('X'), -1, -1
4488 Xalpha_y, TRUE, FALSE,
4489 EL_CHAR('Y'), -1, -1
4492 Xalpha_z, TRUE, FALSE,
4493 EL_CHAR('Z'), -1, -1
4496 Xalpha_arrow_e, TRUE, FALSE,
4497 EL_CHAR('>'), -1, -1
4500 Xalpha_arrow_w, TRUE, FALSE,
4501 EL_CHAR('<'), -1, -1
4504 Xalpha_copyr, TRUE, FALSE,
4505 EL_CHAR('©'), -1, -1
4508 Xalpha_copyr, TRUE, FALSE,
4509 EL_CHAR('©'), -1, -1
4513 Xboom_bug, FALSE, FALSE,
4514 EL_BUG, ACTION_EXPLODING, -1
4517 Xboom_bomb, FALSE, FALSE,
4518 EL_BOMB, ACTION_EXPLODING, -1
4521 Xboom_android, FALSE, FALSE,
4522 EL_EMC_ANDROID, ACTION_OTHER, -1
4525 Xboom_1, FALSE, FALSE,
4526 EL_DEFAULT, ACTION_EXPLODING, -1
4529 Xboom_2, FALSE, FALSE,
4530 EL_DEFAULT, ACTION_EXPLODING, -1
4533 Znormal, FALSE, FALSE,
4537 Zdynamite, FALSE, FALSE,
4541 Zplayer, FALSE, FALSE,
4545 ZBORDER, FALSE, FALSE,
4555 static struct Mapping_EM_to_RND_player
4564 em_player_mapping_list[] =
4568 EL_PLAYER_1, ACTION_MOVING, MV_BIT_UP,
4572 EL_PLAYER_1, ACTION_MOVING, MV_BIT_RIGHT,
4576 EL_PLAYER_1, ACTION_MOVING, MV_BIT_DOWN,
4580 EL_PLAYER_1, ACTION_MOVING, MV_BIT_LEFT,
4584 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_UP,
4588 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_RIGHT,
4592 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_DOWN,
4596 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_LEFT,
4600 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_UP,
4604 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_RIGHT,
4608 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_DOWN,
4612 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_LEFT,
4616 EL_PLAYER_2, ACTION_MOVING, MV_BIT_UP,
4620 EL_PLAYER_2, ACTION_MOVING, MV_BIT_RIGHT,
4624 EL_PLAYER_2, ACTION_MOVING, MV_BIT_DOWN,
4628 EL_PLAYER_2, ACTION_MOVING, MV_BIT_LEFT,
4632 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_UP,
4636 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_RIGHT,
4640 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_DOWN,
4644 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_LEFT,
4648 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_UP,
4652 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_RIGHT,
4656 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_DOWN,
4660 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_LEFT,
4664 EL_PLAYER_1, ACTION_DEFAULT, -1,
4668 EL_PLAYER_2, ACTION_DEFAULT, -1,
4677 int map_element_RND_to_EM(int element_rnd)
4679 static unsigned short mapping_RND_to_EM[NUM_FILE_ELEMENTS];
4680 static boolean mapping_initialized = FALSE;
4682 if (!mapping_initialized)
4686 /* return "Xalpha_quest" for all undefined elements in mapping array */
4687 for (i = 0; i < NUM_FILE_ELEMENTS; i++)
4688 mapping_RND_to_EM[i] = Xalpha_quest;
4690 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
4691 if (em_object_mapping_list[i].is_rnd_to_em_mapping)
4692 mapping_RND_to_EM[em_object_mapping_list[i].element_rnd] =
4693 em_object_mapping_list[i].element_em;
4695 mapping_initialized = TRUE;
4698 if (element_rnd >= 0 && element_rnd < NUM_FILE_ELEMENTS)
4699 return mapping_RND_to_EM[element_rnd];
4701 Error(ERR_WARN, "invalid RND level element %d", element_rnd);
4706 int map_element_EM_to_RND(int element_em)
4708 static unsigned short mapping_EM_to_RND[TILE_MAX];
4709 static boolean mapping_initialized = FALSE;
4711 if (!mapping_initialized)
4715 /* return "EL_UNKNOWN" for all undefined elements in mapping array */
4716 for (i = 0; i < TILE_MAX; i++)
4717 mapping_EM_to_RND[i] = EL_UNKNOWN;
4719 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
4720 mapping_EM_to_RND[em_object_mapping_list[i].element_em] =
4721 em_object_mapping_list[i].element_rnd;
4723 mapping_initialized = TRUE;
4726 if (element_em >= 0 && element_em < TILE_MAX)
4727 return mapping_EM_to_RND[element_em];
4729 Error(ERR_WARN, "invalid EM level element %d", element_em);
4736 int map_element_RND_to_EM(int element_rnd)
4738 static unsigned short mapping_RND_to_EM[NUM_FILE_ELEMENTS];
4739 static boolean mapping_initialized = FALSE;
4746 mapping_RND_to_EM_list[] =
4748 { Xblank, EL_EMPTY },
4749 { Xstone, EL_ROCK },
4751 { Xbug_n, EL_BUG_UP },
4752 { Xbug_e, EL_BUG_RIGHT },
4753 { Xbug_s, EL_BUG_DOWN },
4754 { Xbug_w, EL_BUG_LEFT },
4755 { Xtank_n, EL_SPACESHIP_UP },
4756 { Xtank_e, EL_SPACESHIP_RIGHT },
4757 { Xtank_s, EL_SPACESHIP_DOWN },
4758 { Xtank_w, EL_SPACESHIP_LEFT },
4759 { Xandroid, EL_EMC_ANDROID },
4760 { Xandroid_1_n, EL_EMC_ANDROID_UP },
4761 { Xandroid_1_e, EL_EMC_ANDROID_RIGHT },
4762 { Xandroid_1_w, EL_EMC_ANDROID_LEFT },
4763 { Xandroid_1_s, EL_EMC_ANDROID_DOWN },
4764 { Xspring, EL_SPRING },
4765 { Xeater_n, EL_YAMYAM },
4766 { Xalien, EL_ROBOT },
4767 { Xemerald, EL_EMERALD },
4768 { Xdiamond, EL_DIAMOND },
4769 { Xdrip_fall, EL_AMOEBA_DROP },
4771 { Xballoon, EL_BALLOON },
4772 { Xgrass, EL_EMC_GRASS },
4774 { Xacid_ne, EL_ACID_POOL_TOPRIGHT },
4775 { Xacid_se, EL_ACID_POOL_BOTTOMRIGHT },
4776 { Xacid_s, EL_ACID_POOL_BOTTOM },
4777 { Xacid_sw, EL_ACID_POOL_BOTTOMLEFT },
4778 { Xacid_nw, EL_ACID_POOL_TOPLEFT },
4779 { Xacid_1, EL_ACID },
4780 { Xball_1, EL_EMC_MAGIC_BALL },
4781 { Xgrow_ns, EL_EMC_GROW },
4782 { Xwonderwall, EL_MAGIC_WALL },
4783 { Xamoeba_1, EL_AMOEBA_WET },
4784 { Xdoor_1, EL_EM_GATE_1 },
4785 { Xdoor_2, EL_EM_GATE_2 },
4786 { Xdoor_3, EL_EM_GATE_3 },
4787 { Xdoor_4, EL_EM_GATE_4 },
4788 { Xdoor_5, EL_EMC_GATE_5 },
4789 { Xdoor_6, EL_EMC_GATE_6 },
4790 { Xdoor_7, EL_EMC_GATE_7 },
4791 { Xdoor_8, EL_EMC_GATE_8 },
4792 { Xkey_1, EL_EM_KEY_1 },
4793 { Xkey_2, EL_EM_KEY_2 },
4794 { Xkey_3, EL_EM_KEY_3 },
4795 { Xkey_4, EL_EM_KEY_4 },
4796 { Xkey_5, EL_EMC_KEY_5 },
4797 { Xkey_6, EL_EMC_KEY_6 },
4798 { Xkey_7, EL_EMC_KEY_7 },
4799 { Xkey_8, EL_EMC_KEY_8 },
4800 { Xwind_n, EL_BALLOON_SWITCH_UP },
4801 { Xwind_e, EL_BALLOON_SWITCH_RIGHT },
4802 { Xwind_s, EL_BALLOON_SWITCH_DOWN },
4803 { Xwind_w, EL_BALLOON_SWITCH_LEFT },
4804 { Xwind_nesw, EL_BALLOON_SWITCH_ANY },
4805 { Xwind_stop, EL_BALLOON_SWITCH_NONE },
4806 { Xexit, EL_EXIT_CLOSED },
4807 { Xexit_1, EL_EXIT_OPEN },
4808 { Xdynamite, EL_DYNAMITE },
4809 { Xdynamite_1, EL_DYNAMITE_ACTIVE },
4810 { Xbumper, EL_EMC_BUMPER },
4811 { Xwheel, EL_ROBOT_WHEEL },
4812 { Xswitch, EL_UNKNOWN },
4813 { Xsand, EL_QUICKSAND_EMPTY },
4814 { Xsand_stone, EL_QUICKSAND_FULL },
4815 { Xplant, EL_EMC_PLANT },
4816 { Xlenses, EL_EMC_LENSES },
4817 { Xmagnify, EL_EMC_MAGNIFIER },
4818 { Xdripper, EL_UNKNOWN },
4819 { Xfake_blank, EL_INVISIBLE_WALL },
4820 { Xfake_grass, EL_INVISIBLE_SAND },
4821 { Xfake_door_1, EL_EM_GATE_1_GRAY },
4822 { Xfake_door_2, EL_EM_GATE_2_GRAY },
4823 { Xfake_door_3, EL_EM_GATE_3_GRAY },
4824 { Xfake_door_4, EL_EM_GATE_4_GRAY },
4825 { Xfake_door_5, EL_EMC_GATE_5_GRAY },
4826 { Xfake_door_6, EL_EMC_GATE_6_GRAY },
4827 { Xfake_door_7, EL_EMC_GATE_7_GRAY },
4828 { Xfake_door_8, EL_EMC_GATE_8_GRAY },
4829 { Xsteel_1, EL_STEELWALL },
4830 { Xsteel_2, EL_UNKNOWN },
4831 { Xsteel_3, EL_EMC_STEELWALL_1 },
4832 { Xsteel_4, EL_UNKNOWN },
4833 { Xwall_1, EL_WALL },
4834 { Xwall_2, EL_UNKNOWN },
4835 { Xwall_3, EL_UNKNOWN },
4836 { Xwall_4, EL_UNKNOWN },
4837 { Xround_wall_1, EL_WALL_SLIPPERY },
4838 { Xround_wall_2, EL_UNKNOWN },
4839 { Xround_wall_3, EL_UNKNOWN },
4840 { Xround_wall_4, EL_UNKNOWN },
4841 { Xdecor_1, EL_UNKNOWN },
4842 { Xdecor_2, EL_EMC_WALL_6 },
4843 { Xdecor_3, EL_EMC_WALL_4 },
4844 { Xdecor_4, EL_EMC_WALL_5 },
4845 { Xdecor_5, EL_EMC_WALL_7 },
4846 { Xdecor_6, EL_EMC_WALL_8 },
4847 { Xdecor_7, EL_UNKNOWN },
4848 { Xdecor_8, EL_EMC_WALL_1 },
4849 { Xdecor_9, EL_EMC_WALL_2 },
4850 { Xdecor_10, EL_EMC_WALL_3 },
4851 { Xdecor_11, EL_UNKNOWN },
4852 { Xdecor_12, EL_UNKNOWN },
4853 { Xalpha_0, EL_CHAR('0') },
4854 { Xalpha_1, EL_CHAR('1') },
4855 { Xalpha_2, EL_CHAR('2') },
4856 { Xalpha_3, EL_CHAR('3') },
4857 { Xalpha_4, EL_CHAR('4') },
4858 { Xalpha_5, EL_CHAR('5') },
4859 { Xalpha_6, EL_CHAR('6') },
4860 { Xalpha_7, EL_CHAR('7') },
4861 { Xalpha_8, EL_CHAR('8') },
4862 { Xalpha_9, EL_CHAR('9') },
4863 { Xalpha_excla, EL_CHAR('!') },
4864 { Xalpha_quote, EL_CHAR('"') },
4865 { Xalpha_comma, EL_CHAR(',') },
4866 { Xalpha_minus, EL_CHAR('-') },
4867 { Xalpha_perio, EL_CHAR('.') },
4868 { Xalpha_colon, EL_CHAR(':') },
4869 { Xalpha_quest, EL_CHAR('?') },
4870 { Xalpha_a, EL_CHAR('A') },
4871 { Xalpha_b, EL_CHAR('B') },
4872 { Xalpha_c, EL_CHAR('C') },
4873 { Xalpha_d, EL_CHAR('D') },
4874 { Xalpha_e, EL_CHAR('E') },
4875 { Xalpha_f, EL_CHAR('F') },
4876 { Xalpha_g, EL_CHAR('G') },
4877 { Xalpha_h, EL_CHAR('H') },
4878 { Xalpha_i, EL_CHAR('I') },
4879 { Xalpha_j, EL_CHAR('J') },
4880 { Xalpha_k, EL_CHAR('K') },
4881 { Xalpha_l, EL_CHAR('L') },
4882 { Xalpha_m, EL_CHAR('M') },
4883 { Xalpha_n, EL_CHAR('N') },
4884 { Xalpha_o, EL_CHAR('O') },
4885 { Xalpha_p, EL_CHAR('P') },
4886 { Xalpha_q, EL_CHAR('Q') },
4887 { Xalpha_r, EL_CHAR('R') },
4888 { Xalpha_s, EL_CHAR('S') },
4889 { Xalpha_t, EL_CHAR('T') },
4890 { Xalpha_u, EL_CHAR('U') },
4891 { Xalpha_v, EL_CHAR('V') },
4892 { Xalpha_w, EL_CHAR('W') },
4893 { Xalpha_x, EL_CHAR('X') },
4894 { Xalpha_y, EL_CHAR('Y') },
4895 { Xalpha_z, EL_CHAR('Z') },
4896 { Xalpha_arrow_e, EL_CHAR('>') },
4897 { Xalpha_arrow_w, EL_CHAR('<') },
4898 { Xalpha_copyr, EL_CHAR('©') },
4900 { Zplayer, EL_PLAYER_1 },
4901 { Zplayer, EL_PLAYER_2 },
4902 { Zplayer, EL_PLAYER_3 },
4903 { Zplayer, EL_PLAYER_4 },
4905 { ZBORDER, EL_EMC_LEVEL_BORDER },
4910 if (!mapping_initialized)
4914 /* return "Xalpha_quest" for all undefined elements in mapping array */
4915 for (i = 0; i < NUM_FILE_ELEMENTS; i++)
4916 mapping_RND_to_EM[i] = Xalpha_quest;
4918 for (i = 0; mapping_RND_to_EM_list[i].element_rnd != -1; i++)
4919 mapping_RND_to_EM[mapping_RND_to_EM_list[i].element_rnd] =
4920 mapping_RND_to_EM_list[i].element_em;
4922 mapping_initialized = TRUE;
4925 if (element_rnd >= 0 && element_rnd < NUM_FILE_ELEMENTS)
4926 return mapping_RND_to_EM[element_rnd];
4928 Error(ERR_WARN, "invalid RND level element %d", element_rnd);
4933 int map_element_EM_to_RND(int element_em)
4935 static unsigned short mapping_EM_to_RND[TILE_MAX];
4936 static boolean mapping_initialized = FALSE;
4943 em_object_mapping_list[] =
4945 { Xblank, EL_EMPTY },
4946 { Yacid_splash_eB, EL_EMPTY },
4947 { Yacid_splash_wB, EL_EMPTY },
4949 #ifdef EM_ENGINE_BAD_ROLL
4950 { Xstone_force_e, EL_ROCK },
4951 { Xstone_force_w, EL_ROCK },
4952 { Xnut_force_e, EL_NUT },
4953 { Xnut_force_w, EL_NUT },
4954 { Xspring_force_e, EL_SPRING },
4955 { Xspring_force_w, EL_SPRING },
4956 { Xemerald_force_e, EL_EMERALD },
4957 { Xemerald_force_w, EL_EMERALD },
4958 { Xdiamond_force_e, EL_DIAMOND },
4959 { Xdiamond_force_w, EL_DIAMOND },
4960 { Xbomb_force_e, EL_BOMB },
4961 { Xbomb_force_w, EL_BOMB },
4964 { Xstone, EL_ROCK },
4965 { Xstone_pause, EL_ROCK },
4966 { Xstone_fall, EL_ROCK },
4967 { Ystone_s, EL_ROCK },
4968 { Ystone_sB, EL_ROCK },
4969 { Ystone_e, EL_ROCK },
4970 { Ystone_eB, EL_ROCK },
4971 { Ystone_w, EL_ROCK },
4972 { Ystone_wB, EL_ROCK },
4974 { Xnut_pause, EL_NUT },
4975 { Xnut_fall, EL_NUT },
4977 { Ynut_sB, EL_NUT },
4979 { Ynut_eB, EL_NUT },
4981 { Ynut_wB, EL_NUT },
4982 { Xbug_n, EL_BUG_UP },
4983 { Xbug_e, EL_BUG_RIGHT },
4984 { Xbug_s, EL_BUG_DOWN },
4985 { Xbug_w, EL_BUG_LEFT },
4986 { Xbug_gon, EL_BUG_UP },
4987 { Xbug_goe, EL_BUG_RIGHT },
4988 { Xbug_gos, EL_BUG_DOWN },
4989 { Xbug_gow, EL_BUG_LEFT },
4990 { Ybug_n, EL_BUG_UP },
4991 { Ybug_nB, EL_BUG_UP },
4992 { Ybug_e, EL_BUG_RIGHT },
4993 { Ybug_eB, EL_BUG_RIGHT },
4994 { Ybug_s, EL_BUG_DOWN },
4995 { Ybug_sB, EL_BUG_DOWN },
4996 { Ybug_w, EL_BUG_LEFT },
4997 { Ybug_wB, EL_BUG_LEFT },
4998 { Ybug_w_n, EL_BUG_UP },
4999 { Ybug_n_e, EL_BUG_RIGHT },
5000 { Ybug_e_s, EL_BUG_DOWN },
5001 { Ybug_s_w, EL_BUG_LEFT },
5002 { Ybug_e_n, EL_BUG_UP },
5003 { Ybug_s_e, EL_BUG_RIGHT },
5004 { Ybug_w_s, EL_BUG_DOWN },
5005 { Ybug_n_w, EL_BUG_LEFT },
5006 { Ybug_stone, EL_ROCK },
5007 { Ybug_spring, EL_SPRING },
5008 { Xtank_n, EL_SPACESHIP_UP },
5009 { Xtank_e, EL_SPACESHIP_RIGHT },
5010 { Xtank_s, EL_SPACESHIP_DOWN },
5011 { Xtank_w, EL_SPACESHIP_LEFT },
5012 { Xtank_gon, EL_SPACESHIP_UP },
5013 { Xtank_goe, EL_SPACESHIP_RIGHT },
5014 { Xtank_gos, EL_SPACESHIP_DOWN },
5015 { Xtank_gow, EL_SPACESHIP_LEFT },
5016 { Ytank_n, EL_SPACESHIP_UP },
5017 { Ytank_nB, EL_SPACESHIP_UP },
5018 { Ytank_e, EL_SPACESHIP_RIGHT },
5019 { Ytank_eB, EL_SPACESHIP_RIGHT },
5020 { Ytank_s, EL_SPACESHIP_DOWN },
5021 { Ytank_sB, EL_SPACESHIP_DOWN },
5022 { Ytank_w, EL_SPACESHIP_LEFT },
5023 { Ytank_wB, EL_SPACESHIP_LEFT },
5024 { Ytank_w_n, EL_SPACESHIP_UP },
5025 { Ytank_n_e, EL_SPACESHIP_RIGHT },
5026 { Ytank_e_s, EL_SPACESHIP_DOWN },
5027 { Ytank_s_w, EL_SPACESHIP_LEFT },
5028 { Ytank_e_n, EL_SPACESHIP_UP },
5029 { Ytank_s_e, EL_SPACESHIP_RIGHT },
5030 { Ytank_w_s, EL_SPACESHIP_DOWN },
5031 { Ytank_n_w, EL_SPACESHIP_LEFT },
5032 { Ytank_stone, EL_ROCK },
5033 { Ytank_spring, EL_SPRING },
5034 { Xandroid, EL_EMC_ANDROID },
5035 { Xandroid_1_n, EL_EMC_ANDROID_UP },
5036 { Xandroid_2_n, EL_EMC_ANDROID_UP },
5037 { Xandroid_1_e, EL_EMC_ANDROID_RIGHT },
5038 { Xandroid_2_e, EL_EMC_ANDROID_RIGHT },
5039 { Xandroid_1_w, EL_EMC_ANDROID_LEFT },
5040 { Xandroid_2_w, EL_EMC_ANDROID_LEFT },
5041 { Xandroid_1_s, EL_EMC_ANDROID_DOWN },
5042 { Xandroid_2_s, EL_EMC_ANDROID_DOWN },
5043 { Yandroid_n, EL_EMC_ANDROID_UP },
5044 { Yandroid_nB, EL_EMC_ANDROID_UP },
5045 { Yandroid_ne, EL_EMC_ANDROID_RIGHT_UP },
5046 { Yandroid_neB, EL_EMC_ANDROID_RIGHT_UP },
5047 { Yandroid_e, EL_EMC_ANDROID_RIGHT },
5048 { Yandroid_eB, EL_EMC_ANDROID_RIGHT },
5049 { Yandroid_se, EL_EMC_ANDROID_RIGHT_DOWN },
5050 { Yandroid_seB, EL_EMC_ANDROID_RIGHT_DOWN },
5051 { Yandroid_s, EL_EMC_ANDROID_DOWN },
5052 { Yandroid_sB, EL_EMC_ANDROID_DOWN },
5053 { Yandroid_sw, EL_EMC_ANDROID_LEFT_DOWN },
5054 { Yandroid_swB, EL_EMC_ANDROID_LEFT_DOWN },
5055 { Yandroid_w, EL_EMC_ANDROID_LEFT },
5056 { Yandroid_wB, EL_EMC_ANDROID_LEFT },
5057 { Yandroid_nw, EL_EMC_ANDROID_LEFT_UP },
5058 { Yandroid_nwB, EL_EMC_ANDROID_LEFT_UP },
5059 { Xspring, EL_SPRING },
5060 { Xspring_pause, EL_SPRING },
5061 { Xspring_e, EL_SPRING },
5062 { Xspring_w, EL_SPRING },
5063 { Xspring_fall, EL_SPRING },
5064 { Yspring_s, EL_SPRING },
5065 { Yspring_sB, EL_SPRING },
5066 { Yspring_e, EL_SPRING },
5067 { Yspring_eB, EL_SPRING },
5068 { Yspring_w, EL_SPRING },
5069 { Yspring_wB, EL_SPRING },
5070 { Yspring_kill_e, EL_SPRING },
5071 { Yspring_kill_eB, EL_SPRING },
5072 { Yspring_kill_w, EL_SPRING },
5073 { Yspring_kill_wB, EL_SPRING },
5074 { Xeater_n, EL_YAMYAM },
5075 { Xeater_e, EL_YAMYAM },
5076 { Xeater_w, EL_YAMYAM },
5077 { Xeater_s, EL_YAMYAM },
5078 { Yeater_n, EL_YAMYAM },
5079 { Yeater_nB, EL_YAMYAM },
5080 { Yeater_e, EL_YAMYAM },
5081 { Yeater_eB, EL_YAMYAM },
5082 { Yeater_s, EL_YAMYAM },
5083 { Yeater_sB, EL_YAMYAM },
5084 { Yeater_w, EL_YAMYAM },
5085 { Yeater_wB, EL_YAMYAM },
5086 { Yeater_stone, EL_ROCK },
5087 { Yeater_spring, EL_SPRING },
5088 { Xalien, EL_ROBOT },
5089 { Xalien_pause, EL_ROBOT },
5090 { Yalien_n, EL_ROBOT },
5091 { Yalien_nB, EL_ROBOT },
5092 { Yalien_e, EL_ROBOT },
5093 { Yalien_eB, EL_ROBOT },
5094 { Yalien_s, EL_ROBOT },
5095 { Yalien_sB, EL_ROBOT },
5096 { Yalien_w, EL_ROBOT },
5097 { Yalien_wB, EL_ROBOT },
5098 { Yalien_stone, EL_ROCK },
5099 { Yalien_spring, EL_SPRING },
5100 { Xemerald, EL_EMERALD },
5101 { Xemerald_pause, EL_EMERALD },
5102 { Xemerald_fall, EL_EMERALD },
5103 { Xemerald_shine, EL_EMERALD },
5104 { Yemerald_s, EL_EMERALD },
5105 { Yemerald_sB, EL_EMERALD },
5106 { Yemerald_e, EL_EMERALD },
5107 { Yemerald_eB, EL_EMERALD },
5108 { Yemerald_w, EL_EMERALD },
5109 { Yemerald_wB, EL_EMERALD },
5110 { Yemerald_eat, EL_EMERALD },
5111 { Yemerald_stone, EL_ROCK },
5112 { Xdiamond, EL_DIAMOND },
5113 { Xdiamond_pause, EL_DIAMOND },
5114 { Xdiamond_fall, EL_DIAMOND },
5115 { Xdiamond_shine, EL_DIAMOND },
5116 { Ydiamond_s, EL_DIAMOND },
5117 { Ydiamond_sB, EL_DIAMOND },
5118 { Ydiamond_e, EL_DIAMOND },
5119 { Ydiamond_eB, EL_DIAMOND },
5120 { Ydiamond_w, EL_DIAMOND },
5121 { Ydiamond_wB, EL_DIAMOND },
5122 { Ydiamond_eat, EL_DIAMOND },
5123 { Ydiamond_stone, EL_ROCK },
5124 { Xdrip_fall, EL_AMOEBA_DROP },
5125 { Xdrip_stretch, EL_AMOEBA_DROP },
5126 { Xdrip_stretchB, EL_AMOEBA_DROP },
5127 { Xdrip_eat, EL_AMOEBA_DROP },
5128 { Ydrip_s1, EL_AMOEBA_DROP },
5129 { Ydrip_s1B, EL_AMOEBA_DROP },
5130 { Ydrip_s2, EL_AMOEBA_DROP },
5131 { Ydrip_s2B, EL_AMOEBA_DROP },
5133 { Xbomb_pause, EL_BOMB },
5134 { Xbomb_fall, EL_BOMB },
5135 { Ybomb_s, EL_BOMB },
5136 { Ybomb_sB, EL_BOMB },
5137 { Ybomb_e, EL_BOMB },
5138 { Ybomb_eB, EL_BOMB },
5139 { Ybomb_w, EL_BOMB },
5140 { Ybomb_wB, EL_BOMB },
5141 { Ybomb_eat, EL_BOMB },
5142 { Xballoon, EL_BALLOON },
5143 { Yballoon_n, EL_BALLOON },
5144 { Yballoon_nB, EL_BALLOON },
5145 { Yballoon_e, EL_BALLOON },
5146 { Yballoon_eB, EL_BALLOON },
5147 { Yballoon_s, EL_BALLOON },
5148 { Yballoon_sB, EL_BALLOON },
5149 { Yballoon_w, EL_BALLOON },
5150 { Yballoon_wB, EL_BALLOON },
5151 { Xgrass, EL_SAND },
5152 { Ygrass_nB, EL_SAND },
5153 { Ygrass_eB, EL_SAND },
5154 { Ygrass_sB, EL_SAND },
5155 { Ygrass_wB, EL_SAND },
5157 { Ydirt_nB, EL_SAND },
5158 { Ydirt_eB, EL_SAND },
5159 { Ydirt_sB, EL_SAND },
5160 { Ydirt_wB, EL_SAND },
5161 { Xacid_ne, EL_ACID_POOL_TOPRIGHT },
5162 { Xacid_se, EL_ACID_POOL_BOTTOMRIGHT },
5163 { Xacid_s, EL_ACID_POOL_BOTTOM },
5164 { Xacid_sw, EL_ACID_POOL_BOTTOMLEFT },
5165 { Xacid_nw, EL_ACID_POOL_TOPLEFT },
5166 { Xacid_1, EL_ACID },
5167 { Xacid_2, EL_ACID },
5168 { Xacid_3, EL_ACID },
5169 { Xacid_4, EL_ACID },
5170 { Xacid_5, EL_ACID },
5171 { Xacid_6, EL_ACID },
5172 { Xacid_7, EL_ACID },
5173 { Xacid_8, EL_ACID },
5174 { Xball_1, EL_EMC_MAGIC_BALL },
5175 { Xball_1B, EL_EMC_MAGIC_BALL },
5176 { Xball_2, EL_EMC_MAGIC_BALL },
5177 { Xball_2B, EL_EMC_MAGIC_BALL },
5178 { Yball_eat, EL_EMC_MAGIC_BALL },
5179 { Xgrow_ns, EL_EMC_GROW },
5180 { Ygrow_ns_eat, EL_EMC_GROW },
5181 { Xgrow_ew, EL_EMC_GROW },
5182 { Ygrow_ew_eat, EL_EMC_GROW },
5183 { Xwonderwall, EL_MAGIC_WALL },
5184 { XwonderwallB, EL_MAGIC_WALL },
5185 { Xamoeba_1, EL_AMOEBA_WET },
5186 { Xamoeba_2, EL_AMOEBA_WET },
5187 { Xamoeba_3, EL_AMOEBA_WET },
5188 { Xamoeba_4, EL_AMOEBA_WET },
5189 { Xamoeba_5, EL_AMOEBA_WET },
5190 { Xamoeba_6, EL_AMOEBA_WET },
5191 { Xamoeba_7, EL_AMOEBA_WET },
5192 { Xamoeba_8, EL_AMOEBA_WET },
5193 { Xdoor_1, EL_EM_GATE_1 },
5194 { Xdoor_2, EL_EM_GATE_2 },
5195 { Xdoor_3, EL_EM_GATE_3 },
5196 { Xdoor_4, EL_EM_GATE_4 },
5197 { Xdoor_5, EL_EMC_GATE_5 },
5198 { Xdoor_6, EL_EMC_GATE_6 },
5199 { Xdoor_7, EL_EMC_GATE_7 },
5200 { Xdoor_8, EL_EMC_GATE_8 },
5201 { Xkey_1, EL_EM_KEY_1 },
5202 { Xkey_2, EL_EM_KEY_2 },
5203 { Xkey_3, EL_EM_KEY_3 },
5204 { Xkey_4, EL_EM_KEY_4 },
5205 { Xkey_5, EL_EMC_KEY_5 },
5206 { Xkey_6, EL_EMC_KEY_6 },
5207 { Xkey_7, EL_EMC_KEY_7 },
5208 { Xkey_8, EL_EMC_KEY_8 },
5209 { Xwind_n, EL_BALLOON_SWITCH_UP },
5210 { Xwind_e, EL_BALLOON_SWITCH_RIGHT },
5211 { Xwind_s, EL_BALLOON_SWITCH_DOWN },
5212 { Xwind_w, EL_BALLOON_SWITCH_LEFT },
5213 { Xwind_nesw, EL_BALLOON_SWITCH_ANY },
5214 { Xwind_stop, EL_BALLOON_SWITCH_NONE },
5215 { Xexit, EL_EXIT_CLOSED },
5216 { Xexit_1, EL_EXIT_OPEN },
5217 { Xexit_2, EL_EXIT_OPEN },
5218 { Xexit_3, EL_EXIT_OPEN },
5219 { Xdynamite, EL_DYNAMITE },
5220 { Ydynamite_eat, EL_DYNAMITE },
5221 { Xdynamite_1, EL_DYNAMITE_ACTIVE },
5222 { Xdynamite_2, EL_DYNAMITE_ACTIVE },
5223 { Xdynamite_3, EL_DYNAMITE_ACTIVE },
5224 { Xdynamite_4, EL_DYNAMITE_ACTIVE },
5225 { Xbumper, EL_EMC_BUMPER },
5226 { XbumperB, EL_EMC_BUMPER },
5227 { Xwheel, EL_ROBOT_WHEEL },
5228 { XwheelB, EL_ROBOT_WHEEL },
5229 { Xswitch, EL_UNKNOWN },
5230 { XswitchB, EL_UNKNOWN },
5231 { Xsand, EL_QUICKSAND_EMPTY },
5232 { Xsand_stone, EL_QUICKSAND_FULL },
5233 { Xsand_stonein_1, EL_QUICKSAND_FULL },
5234 { Xsand_stonein_2, EL_QUICKSAND_FULL },
5235 { Xsand_stonein_3, EL_QUICKSAND_FULL },
5236 { Xsand_stonein_4, EL_QUICKSAND_FULL },
5237 { Xsand_stonesand_1, EL_QUICKSAND_FULL },
5238 { Xsand_stonesand_2, EL_QUICKSAND_FULL },
5239 { Xsand_stonesand_3, EL_QUICKSAND_FULL },
5240 { Xsand_stonesand_4, EL_QUICKSAND_FULL },
5241 { Xsand_stoneout_1, EL_QUICKSAND_FULL },
5242 { Xsand_stoneout_2, EL_QUICKSAND_FULL },
5243 { Xsand_sandstone_1, EL_QUICKSAND_FULL },
5244 { Xsand_sandstone_2, EL_QUICKSAND_FULL },
5245 { Xsand_sandstone_3, EL_QUICKSAND_FULL },
5246 { Xsand_sandstone_4, EL_QUICKSAND_FULL },
5247 { Xplant, EL_EMC_PLANT },
5248 { Yplant, EL_EMC_PLANT },
5249 { Xlenses, EL_EMC_LENSES },
5250 { Xmagnify, EL_EMC_MAGNIFIER },
5251 { Xdripper, EL_UNKNOWN },
5252 { XdripperB, EL_UNKNOWN },
5253 { Xfake_blank, EL_INVISIBLE_WALL },
5254 { Xfake_blankB, EL_INVISIBLE_WALL },
5255 { Xfake_grass, EL_INVISIBLE_SAND },
5256 { Xfake_grassB, EL_INVISIBLE_SAND },
5257 { Xfake_door_1, EL_EM_GATE_1_GRAY },
5258 { Xfake_door_2, EL_EM_GATE_2_GRAY },
5259 { Xfake_door_3, EL_EM_GATE_3_GRAY },
5260 { Xfake_door_4, EL_EM_GATE_4_GRAY },
5261 { Xfake_door_5, EL_EMC_GATE_5_GRAY },
5262 { Xfake_door_6, EL_EMC_GATE_6_GRAY },
5263 { Xfake_door_7, EL_EMC_GATE_7_GRAY },
5264 { Xfake_door_8, EL_EMC_GATE_8_GRAY },
5265 { Xsteel_1, EL_STEELWALL },
5266 { Xsteel_2, EL_UNKNOWN },
5267 { Xsteel_3, EL_EMC_STEELWALL_1 },
5268 { Xsteel_4, EL_UNKNOWN },
5269 { Xwall_1, EL_WALL },
5270 { Xwall_2, EL_UNKNOWN },
5271 { Xwall_3, EL_UNKNOWN },
5272 { Xwall_4, EL_UNKNOWN },
5273 { Xround_wall_1, EL_WALL_SLIPPERY },
5274 { Xround_wall_2, EL_UNKNOWN },
5275 { Xround_wall_3, EL_UNKNOWN },
5276 { Xround_wall_4, EL_UNKNOWN },
5277 { Xdecor_1, EL_UNKNOWN },
5278 { Xdecor_2, EL_EMC_WALL_6 },
5279 { Xdecor_3, EL_EMC_WALL_4 },
5280 { Xdecor_4, EL_EMC_WALL_5 },
5281 { Xdecor_5, EL_EMC_WALL_7 },
5282 { Xdecor_6, EL_EMC_WALL_8 },
5283 { Xdecor_7, EL_UNKNOWN },
5284 { Xdecor_8, EL_EMC_WALL_1 },
5285 { Xdecor_9, EL_EMC_WALL_2 },
5286 { Xdecor_10, EL_EMC_WALL_3 },
5287 { Xdecor_11, EL_UNKNOWN },
5288 { Xdecor_12, EL_UNKNOWN },
5289 { Xalpha_0, EL_CHAR('0') },
5290 { Xalpha_1, EL_CHAR('1') },
5291 { Xalpha_2, EL_CHAR('2') },
5292 { Xalpha_3, EL_CHAR('3') },
5293 { Xalpha_4, EL_CHAR('4') },
5294 { Xalpha_5, EL_CHAR('5') },
5295 { Xalpha_6, EL_CHAR('6') },
5296 { Xalpha_7, EL_CHAR('7') },
5297 { Xalpha_8, EL_CHAR('8') },
5298 { Xalpha_9, EL_CHAR('9') },
5299 { Xalpha_excla, EL_CHAR('!') },
5300 { Xalpha_quote, EL_CHAR('"') },
5301 { Xalpha_comma, EL_CHAR(',') },
5302 { Xalpha_minus, EL_CHAR('-') },
5303 { Xalpha_perio, EL_CHAR('.') },
5304 { Xalpha_colon, EL_CHAR(':') },
5305 { Xalpha_quest, EL_CHAR('?') },
5306 { Xalpha_a, EL_CHAR('A') },
5307 { Xalpha_b, EL_CHAR('B') },
5308 { Xalpha_c, EL_CHAR('C') },
5309 { Xalpha_d, EL_CHAR('D') },
5310 { Xalpha_e, EL_CHAR('E') },
5311 { Xalpha_f, EL_CHAR('F') },
5312 { Xalpha_g, EL_CHAR('G') },
5313 { Xalpha_h, EL_CHAR('H') },
5314 { Xalpha_i, EL_CHAR('I') },
5315 { Xalpha_j, EL_CHAR('J') },
5316 { Xalpha_k, EL_CHAR('K') },
5317 { Xalpha_l, EL_CHAR('L') },
5318 { Xalpha_m, EL_CHAR('M') },
5319 { Xalpha_n, EL_CHAR('N') },
5320 { Xalpha_o, EL_CHAR('O') },
5321 { Xalpha_p, EL_CHAR('P') },
5322 { Xalpha_q, EL_CHAR('Q') },
5323 { Xalpha_r, EL_CHAR('R') },
5324 { Xalpha_s, EL_CHAR('S') },
5325 { Xalpha_t, EL_CHAR('T') },
5326 { Xalpha_u, EL_CHAR('U') },
5327 { Xalpha_v, EL_CHAR('V') },
5328 { Xalpha_w, EL_CHAR('W') },
5329 { Xalpha_x, EL_CHAR('X') },
5330 { Xalpha_y, EL_CHAR('Y') },
5331 { Xalpha_z, EL_CHAR('Z') },
5332 { Xalpha_arrow_e, EL_CHAR('>') },
5333 { Xalpha_arrow_w, EL_CHAR('<') },
5334 { Xalpha_copyr, EL_CHAR('©') },
5336 { Zplayer, EL_PLAYER_1 },
5338 { ZBORDER, EL_EMC_LEVEL_BORDER },
5343 if (!mapping_initialized)
5347 /* return "EL_UNKNOWN" for all undefined elements in mapping array */
5348 for (i = 0; i < TILE_MAX; i++)
5349 mapping_EM_to_RND[i] = EL_UNKNOWN;
5351 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
5352 mapping_EM_to_RND[em_object_mapping_list[i].element_em] =
5353 em_object_mapping_list[i].element_rnd;
5355 mapping_initialized = TRUE;
5358 if (element_em >= 0 && element_em < TILE_MAX)
5359 return mapping_EM_to_RND[element_em];
5361 Error(ERR_WARN, "invalid EM level element %d", element_em);
5368 int get_next_element(int element)
5372 case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL;
5373 case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY;
5374 case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL;
5375 case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_ACTIVE;
5376 case EL_BD_MAGIC_WALL_FILLING: return EL_BD_MAGIC_WALL_FULL;
5377 case EL_BD_MAGIC_WALL_EMPTYING: return EL_BD_MAGIC_WALL_ACTIVE;
5378 case EL_AMOEBA_DROPPING: return EL_AMOEBA_WET;
5380 default: return element;
5385 int el_act_dir2img(int element, int action, int direction)
5387 element = GFX_ELEMENT(element);
5389 if (direction == MV_NONE)
5390 return element_info[element].graphic[action];
5392 direction = MV_DIR_BIT(direction);
5394 return element_info[element].direction_graphic[action][direction];
5397 int el_act_dir2img(int element, int action, int direction)
5399 element = GFX_ELEMENT(element);
5400 direction = MV_DIR_BIT(direction); /* default: MV_NONE => MV_DOWN */
5402 /* direction_graphic[][] == graphic[] for undefined direction graphics */
5403 return element_info[element].direction_graphic[action][direction];
5408 static int el_act_dir2crm(int element, int action, int direction)
5410 element = GFX_ELEMENT(element);
5412 if (direction == MV_NONE)
5413 return element_info[element].crumbled[action];
5415 direction = MV_DIR_BIT(direction);
5417 return element_info[element].direction_crumbled[action][direction];
5420 static int el_act_dir2crm(int element, int action, int direction)
5422 element = GFX_ELEMENT(element);
5423 direction = MV_DIR_BIT(direction); /* default: MV_NONE => MV_DOWN */
5425 /* direction_graphic[][] == graphic[] for undefined direction graphics */
5426 return element_info[element].direction_crumbled[action][direction];
5430 int el_act2img(int element, int action)
5432 element = GFX_ELEMENT(element);
5434 return element_info[element].graphic[action];
5437 int el_act2crm(int element, int action)
5439 element = GFX_ELEMENT(element);
5441 return element_info[element].crumbled[action];
5444 int el_dir2img(int element, int direction)
5446 element = GFX_ELEMENT(element);
5448 return el_act_dir2img(element, ACTION_DEFAULT, direction);
5451 int el2baseimg(int element)
5453 return element_info[element].graphic[ACTION_DEFAULT];
5456 int el2img(int element)
5458 element = GFX_ELEMENT(element);
5460 return element_info[element].graphic[ACTION_DEFAULT];
5463 int el2edimg(int element)
5465 element = GFX_ELEMENT(element);
5467 return element_info[element].special_graphic[GFX_SPECIAL_ARG_EDITOR];
5470 int el2preimg(int element)
5472 element = GFX_ELEMENT(element);
5474 return element_info[element].special_graphic[GFX_SPECIAL_ARG_PREVIEW];
5477 int font2baseimg(int font_nr)
5479 return font_info[font_nr].special_graphic[GFX_SPECIAL_ARG_DEFAULT];
5482 int getGameFrameDelay_EM(int native_em_game_frame_delay)
5484 int game_frame_delay_value;
5486 game_frame_delay_value =
5487 (tape.playing && tape.fast_forward ? FfwdFrameDelay :
5488 GameFrameDelay == GAME_FRAME_DELAY ? native_em_game_frame_delay :
5491 if (tape.playing && tape.warp_forward && !tape.pausing)
5492 game_frame_delay_value = 0;
5494 return game_frame_delay_value;
5497 unsigned int InitRND(long seed)
5499 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
5500 return InitEngineRND_EM(seed);
5502 return InitEngineRND(seed);
5505 #define DEBUG_EM_GFX 0
5507 void InitGraphicInfo_EM(void)
5509 struct Mapping_EM_to_RND_object object_mapping[TILE_MAX];
5510 struct Mapping_EM_to_RND_player player_mapping[2][SPR_MAX];
5514 if (graphic_info_em_object[0][0].bitmap == NULL)
5516 /* EM graphics not yet initialized in em_open_all() */
5522 /* always start with reliable default values */
5523 for (i = 0; i < TILE_MAX; i++)
5525 object_mapping[i].element_rnd = EL_UNKNOWN;
5526 object_mapping[i].is_backside = FALSE;
5527 object_mapping[i].action = ACTION_DEFAULT;
5528 object_mapping[i].direction = MV_NONE;
5531 /* always start with reliable default values */
5532 for (p = 0; p < 2; p++)
5534 for (i = 0; i < SPR_MAX; i++)
5536 player_mapping[p][i].element_rnd = EL_UNKNOWN;
5537 player_mapping[p][i].action = ACTION_DEFAULT;
5538 player_mapping[p][i].direction = MV_NONE;
5542 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
5544 int e = em_object_mapping_list[i].element_em;
5546 object_mapping[e].element_rnd = em_object_mapping_list[i].element_rnd;
5547 object_mapping[e].is_backside = em_object_mapping_list[i].is_backside;
5549 if (em_object_mapping_list[i].action != -1)
5550 object_mapping[e].action = em_object_mapping_list[i].action;
5552 if (em_object_mapping_list[i].direction != -1)
5553 object_mapping[e].direction = (1 << em_object_mapping_list[i].direction);
5556 for (i = 0; em_player_mapping_list[i].action_em != -1; i++)
5558 int a = em_player_mapping_list[i].action_em;
5559 int p = em_player_mapping_list[i].player_nr;
5561 player_mapping[p][a].element_rnd = em_player_mapping_list[i].element_rnd;
5563 if (em_player_mapping_list[i].action != -1)
5564 player_mapping[p][a].action = em_player_mapping_list[i].action;
5566 if (em_player_mapping_list[i].direction != -1)
5567 player_mapping[p][a].direction =
5568 (1 << em_player_mapping_list[i].direction);
5571 for (i = 0; i < TILE_MAX; i++)
5573 int element = object_mapping[i].element_rnd;
5574 int action = object_mapping[i].action;
5575 int direction = object_mapping[i].direction;
5576 boolean is_backside = object_mapping[i].is_backside;
5577 boolean action_removing = (action == ACTION_DIGGING ||
5578 action == ACTION_SNAPPING ||
5579 action == ACTION_COLLECTING);
5580 boolean action_exploding = ((action == ACTION_EXPLODING ||
5581 action == ACTION_SMASHED_BY_ROCK ||
5582 action == ACTION_SMASHED_BY_SPRING) &&
5583 element != EL_DIAMOND);
5584 boolean action_active = (action == ACTION_ACTIVE);
5585 boolean action_other = (action == ACTION_OTHER);
5587 for (j = 0; j < 8; j++)
5589 int effective_element = (j > 5 && i == Yacid_splash_eB ? EL_EMPTY :
5590 j > 5 && i == Yacid_splash_wB ? EL_EMPTY :
5592 i == Xdrip_stretch ? element :
5593 i == Xdrip_stretchB ? element :
5594 i == Ydrip_s1 ? element :
5595 i == Ydrip_s1B ? element :
5596 i == Xball_1B ? element :
5597 i == Xball_2 ? element :
5598 i == Xball_2B ? element :
5599 i == Yball_eat ? element :
5600 i == Ykey_1_eat ? element :
5601 i == Ykey_2_eat ? element :
5602 i == Ykey_3_eat ? element :
5603 i == Ykey_4_eat ? element :
5604 i == Ykey_5_eat ? element :
5605 i == Ykey_6_eat ? element :
5606 i == Ykey_7_eat ? element :
5607 i == Ykey_8_eat ? element :
5608 i == Ylenses_eat ? element :
5609 i == Ymagnify_eat ? element :
5610 i == Ygrass_eat ? element :
5611 i == Ydirt_eat ? element :
5612 i == Yspring_kill_e ? EL_SPRING :
5613 i == Yspring_kill_w ? EL_SPRING :
5614 i == Yemerald_stone ? EL_EMERALD :
5615 i == Ydiamond_stone ? EL_ROCK :
5616 i == Xsand_stonein_4 ? EL_EMPTY :
5617 i == Xsand_stoneout_2 ? EL_ROCK :
5618 is_backside ? EL_EMPTY :
5619 action_removing ? EL_EMPTY :
5621 int effective_action = (j < 7 ? action :
5622 i == Xdrip_stretch ? action :
5623 i == Xdrip_stretchB ? action :
5624 i == Ydrip_s1 ? action :
5625 i == Ydrip_s1B ? action :
5626 i == Xball_1B ? action :
5627 i == Xball_2 ? action :
5628 i == Xball_2B ? action :
5629 i == Yball_eat ? action :
5630 i == Ykey_1_eat ? action :
5631 i == Ykey_2_eat ? action :
5632 i == Ykey_3_eat ? action :
5633 i == Ykey_4_eat ? action :
5634 i == Ykey_5_eat ? action :
5635 i == Ykey_6_eat ? action :
5636 i == Ykey_7_eat ? action :
5637 i == Ykey_8_eat ? action :
5638 i == Ylenses_eat ? action :
5639 i == Ymagnify_eat ? action :
5640 i == Ygrass_eat ? action :
5641 i == Ydirt_eat ? action :
5642 i == Xsand_stonein_1 ? action :
5643 i == Xsand_stonein_2 ? action :
5644 i == Xsand_stonein_3 ? action :
5645 i == Xsand_stonein_4 ? action :
5646 i == Xsand_stoneout_1 ? action :
5647 i == Xsand_stoneout_2 ? action :
5648 i == Xboom_android ? ACTION_EXPLODING :
5649 action_exploding ? ACTION_EXPLODING :
5650 action_active ? action :
5651 action_other ? action :
5653 int graphic = (el_act_dir2img(effective_element, effective_action,
5655 int crumbled = (el_act_dir2crm(effective_element, effective_action,
5657 int base_graphic = el_act2img(effective_element, ACTION_DEFAULT);
5658 int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT);
5659 boolean has_crumbled_graphics = (base_crumbled != base_graphic);
5660 struct GraphicInfo *g = &graphic_info[graphic];
5661 struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
5664 /* ensure to get symmetric 3-frame, 2-delay animations as used in EM */
5665 boolean special_animation = (action != ACTION_DEFAULT &&
5666 g->anim_frames == 3 &&
5667 g->anim_delay == 2 &&
5668 g->anim_mode & ANIM_LINEAR);
5669 int sync_frame = (i == Xdrip_stretch ? 7 :
5670 i == Xdrip_stretchB ? 7 :
5671 i == Ydrip_s2 ? j + 8 :
5672 i == Ydrip_s2B ? j + 8 :
5681 i == Xfake_acid_1 ? 0 :
5682 i == Xfake_acid_2 ? 10 :
5683 i == Xfake_acid_3 ? 20 :
5684 i == Xfake_acid_4 ? 30 :
5685 i == Xfake_acid_5 ? 40 :
5686 i == Xfake_acid_6 ? 50 :
5687 i == Xfake_acid_7 ? 60 :
5688 i == Xfake_acid_8 ? 70 :
5690 i == Xball_2B ? j + 8 :
5691 i == Yball_eat ? j + 1 :
5692 i == Ykey_1_eat ? j + 1 :
5693 i == Ykey_2_eat ? j + 1 :
5694 i == Ykey_3_eat ? j + 1 :
5695 i == Ykey_4_eat ? j + 1 :
5696 i == Ykey_5_eat ? j + 1 :
5697 i == Ykey_6_eat ? j + 1 :
5698 i == Ykey_7_eat ? j + 1 :
5699 i == Ykey_8_eat ? j + 1 :
5700 i == Ylenses_eat ? j + 1 :
5701 i == Ymagnify_eat ? j + 1 :
5702 i == Ygrass_eat ? j + 1 :
5703 i == Ydirt_eat ? j + 1 :
5704 i == Xamoeba_1 ? 0 :
5705 i == Xamoeba_2 ? 1 :
5706 i == Xamoeba_3 ? 2 :
5707 i == Xamoeba_4 ? 3 :
5708 i == Xamoeba_5 ? 0 :
5709 i == Xamoeba_6 ? 1 :
5710 i == Xamoeba_7 ? 2 :
5711 i == Xamoeba_8 ? 3 :
5712 i == Xexit_2 ? j + 8 :
5713 i == Xexit_3 ? j + 16 :
5714 i == Xdynamite_1 ? 0 :
5715 i == Xdynamite_2 ? 20 :
5716 i == Xdynamite_3 ? 40 :
5717 i == Xdynamite_4 ? 60 :
5718 i == Xsand_stonein_1 ? j + 1 :
5719 i == Xsand_stonein_2 ? j + 9 :
5720 i == Xsand_stonein_3 ? j + 17 :
5721 i == Xsand_stonein_4 ? j + 25 :
5722 i == Xsand_stoneout_1 && j == 0 ? 0 :
5723 i == Xsand_stoneout_1 && j == 1 ? 0 :
5724 i == Xsand_stoneout_1 && j == 2 ? 1 :
5725 i == Xsand_stoneout_1 && j == 3 ? 2 :
5726 i == Xsand_stoneout_1 && j == 4 ? 2 :
5727 i == Xsand_stoneout_1 && j == 5 ? 3 :
5728 i == Xsand_stoneout_1 && j == 6 ? 4 :
5729 i == Xsand_stoneout_1 && j == 7 ? 4 :
5730 i == Xsand_stoneout_2 && j == 0 ? 5 :
5731 i == Xsand_stoneout_2 && j == 1 ? 6 :
5732 i == Xsand_stoneout_2 && j == 2 ? 7 :
5733 i == Xsand_stoneout_2 && j == 3 ? 8 :
5734 i == Xsand_stoneout_2 && j == 4 ? 9 :
5735 i == Xsand_stoneout_2 && j == 5 ? 11 :
5736 i == Xsand_stoneout_2 && j == 6 ? 13 :
5737 i == Xsand_stoneout_2 && j == 7 ? 15 :
5738 i == Xboom_bug && j == 1 ? 2 :
5739 i == Xboom_bug && j == 2 ? 2 :
5740 i == Xboom_bug && j == 3 ? 4 :
5741 i == Xboom_bug && j == 4 ? 4 :
5742 i == Xboom_bug && j == 5 ? 2 :
5743 i == Xboom_bug && j == 6 ? 2 :
5744 i == Xboom_bug && j == 7 ? 0 :
5745 i == Xboom_bomb && j == 1 ? 2 :
5746 i == Xboom_bomb && j == 2 ? 2 :
5747 i == Xboom_bomb && j == 3 ? 4 :
5748 i == Xboom_bomb && j == 4 ? 4 :
5749 i == Xboom_bomb && j == 5 ? 2 :
5750 i == Xboom_bomb && j == 6 ? 2 :
5751 i == Xboom_bomb && j == 7 ? 0 :
5752 i == Xboom_android && j == 7 ? 6 :
5753 i == Xboom_1 && j == 1 ? 2 :
5754 i == Xboom_1 && j == 2 ? 2 :
5755 i == Xboom_1 && j == 3 ? 4 :
5756 i == Xboom_1 && j == 4 ? 4 :
5757 i == Xboom_1 && j == 5 ? 6 :
5758 i == Xboom_1 && j == 6 ? 6 :
5759 i == Xboom_1 && j == 7 ? 8 :
5760 i == Xboom_2 && j == 0 ? 8 :
5761 i == Xboom_2 && j == 1 ? 8 :
5762 i == Xboom_2 && j == 2 ? 10 :
5763 i == Xboom_2 && j == 3 ? 10 :
5764 i == Xboom_2 && j == 4 ? 10 :
5765 i == Xboom_2 && j == 5 ? 12 :
5766 i == Xboom_2 && j == 6 ? 12 :
5767 i == Xboom_2 && j == 7 ? 12 :
5768 special_animation && j == 4 ? 3 :
5769 effective_action != action ? 0 :
5773 Bitmap *debug_bitmap = g_em->bitmap;
5774 int debug_src_x = g_em->src_x;
5775 int debug_src_y = g_em->src_y;
5778 int frame = getAnimationFrame(g->anim_frames,
5781 g->anim_start_frame,
5784 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y,
5785 g->double_movement && is_backside);
5787 g_em->bitmap = src_bitmap;
5788 g_em->src_x = src_x;
5789 g_em->src_y = src_y;
5790 g_em->src_offset_x = 0;
5791 g_em->src_offset_y = 0;
5792 g_em->dst_offset_x = 0;
5793 g_em->dst_offset_y = 0;
5794 g_em->width = TILEX;
5795 g_em->height = TILEY;
5797 g_em->crumbled_bitmap = NULL;
5798 g_em->crumbled_src_x = 0;
5799 g_em->crumbled_src_y = 0;
5800 g_em->crumbled_border_size = 0;
5802 g_em->has_crumbled_graphics = FALSE;
5803 g_em->preserve_background = FALSE;
5806 if (has_crumbled_graphics && crumbled == IMG_EMPTY_SPACE)
5807 printf("::: empty crumbled: %d [%s], %d, %d\n",
5808 effective_element, element_info[effective_element].token_name,
5809 effective_action, direction);
5812 /* if element can be crumbled, but certain action graphics are just empty
5813 space (like snapping sand with the original R'n'D graphics), do not
5814 treat these empty space graphics as crumbled graphics in EMC engine */
5815 if (has_crumbled_graphics && crumbled != IMG_EMPTY_SPACE)
5817 getGraphicSource(crumbled, frame, &src_bitmap, &src_x, &src_y);
5819 g_em->has_crumbled_graphics = TRUE;
5820 g_em->crumbled_bitmap = src_bitmap;
5821 g_em->crumbled_src_x = src_x;
5822 g_em->crumbled_src_y = src_y;
5823 g_em->crumbled_border_size = graphic_info[crumbled].border_size;
5826 if (!g->double_movement && (effective_action == ACTION_FALLING ||
5827 effective_action == ACTION_MOVING ||
5828 effective_action == ACTION_PUSHING))
5831 (effective_action == ACTION_FALLING ? MV_DOWN : direction);
5832 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? 1 : 0);
5833 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? 1 : 0);
5834 int num_steps = (i == Ydrip_s1 ||
5837 i == Ydrip_s2B ? 16 : 8);
5838 int cx = ABS(dx) * (TILEX / num_steps);
5839 int cy = ABS(dy) * (TILEY / num_steps);
5840 int step_frame = (i == Ydrip_s2 ||
5841 i == Ydrip_s2B ? j + 8 : j) + 1;
5842 int step = (is_backside ? step_frame : num_steps - step_frame);
5844 if (is_backside) /* tile where movement starts */
5846 if (dx < 0 || dy < 0)
5848 g_em->src_offset_x = cx * step;
5849 g_em->src_offset_y = cy * step;
5853 g_em->dst_offset_x = cx * step;
5854 g_em->dst_offset_y = cy * step;
5857 else /* tile where movement ends */
5859 if (dx < 0 || dy < 0)
5861 g_em->dst_offset_x = cx * step;
5862 g_em->dst_offset_y = cy * step;
5866 g_em->src_offset_x = cx * step;
5867 g_em->src_offset_y = cy * step;
5871 g_em->width = TILEX - cx * step;
5872 g_em->height = TILEY - cy * step;
5875 /* create unique graphic identifier to decide if tile must be redrawn */
5876 /* bit 31 - 16 (16 bit): EM style element
5877 bit 15 - 12 ( 4 bit): EM style frame
5878 bit 11 - 6 ( 6 bit): graphic width
5879 bit 5 - 0 ( 6 bit): graphic height */
5880 g_em->unique_identifier =
5881 (i << 16) | (j << 12) | (g_em->width << 6) | g_em->height;
5884 if (g_em->bitmap != debug_bitmap ||
5885 g_em->src_x != debug_src_x ||
5886 g_em->src_y != debug_src_y ||
5887 g_em->src_offset_x != 0 ||
5888 g_em->src_offset_y != 0 ||
5889 g_em->dst_offset_x != 0 ||
5890 g_em->dst_offset_y != 0 ||
5891 g_em->width != TILEX ||
5892 g_em->height != TILEY)
5894 static int last_i = -1;
5902 printf("::: EMC GFX ERROR for element %d -> %d ('%s', '%s', %d)",
5903 i, element, element_info[element].token_name,
5904 element_action_info[effective_action].suffix, direction);
5906 if (element != effective_element)
5907 printf(" [%d ('%s')]",
5909 element_info[effective_element].token_name);
5913 if (g_em->bitmap != debug_bitmap)
5914 printf(" %d (%d): different bitmap! (0x%08x != 0x%08x)\n",
5915 j, is_backside, (int)(g_em->bitmap), (int)(debug_bitmap));
5917 if (g_em->src_x != debug_src_x ||
5918 g_em->src_y != debug_src_y)
5919 printf(" frame %d (%c): %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
5920 j, (is_backside ? 'B' : 'F'),
5921 g_em->src_x, g_em->src_y,
5922 g_em->src_x / 32, g_em->src_y / 32,
5923 debug_src_x, debug_src_y,
5924 debug_src_x / 32, debug_src_y / 32);
5926 if (g_em->src_offset_x != 0 ||
5927 g_em->src_offset_y != 0 ||
5928 g_em->dst_offset_x != 0 ||
5929 g_em->dst_offset_y != 0)
5930 printf(" %d (%d): offsets %d,%d and %d,%d should be all 0\n",
5932 g_em->src_offset_x, g_em->src_offset_y,
5933 g_em->dst_offset_x, g_em->dst_offset_y);
5935 if (g_em->width != TILEX ||
5936 g_em->height != TILEY)
5937 printf(" %d (%d): size %d,%d should be %d,%d\n",
5939 g_em->width, g_em->height, TILEX, TILEY);
5946 for (i = 0; i < TILE_MAX; i++)
5948 for (j = 0; j < 8; j++)
5950 int element = object_mapping[i].element_rnd;
5951 int action = object_mapping[i].action;
5953 if (action == ACTION_SMASHED_BY_ROCK &&
5954 element_info[element].graphic[action] ==
5955 element_info[element].graphic[ACTION_DEFAULT])
5957 /* no separate animation for "smashed by rock" -- use rock instead */
5958 struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
5959 struct GraphicInfo_EM *g_xx = &graphic_info_em_object[Ystone_s][7 - j];
5961 g_em->bitmap = g_xx->bitmap;
5962 g_em->src_x = g_xx->src_x;
5963 g_em->src_y = g_xx->src_y;
5964 g_em->src_offset_x = g_xx->src_offset_x;
5965 g_em->src_offset_y = g_xx->src_offset_y;
5966 g_em->dst_offset_x = g_xx->dst_offset_x;
5967 g_em->dst_offset_y = g_xx->dst_offset_y;
5968 g_em->width = g_xx->width;
5969 g_em->height = g_xx->height;
5971 g_em->preserve_background = TRUE;
5976 for (p = 0; p < 2; p++)
5978 for (i = 0; i < SPR_MAX; i++)
5980 int element = player_mapping[p][i].element_rnd;
5981 int action = player_mapping[p][i].action;
5982 int direction = player_mapping[p][i].direction;
5984 for (j = 0; j < 8; j++)
5986 int effective_element = element;
5987 int effective_action = action;
5988 int graphic = (direction == MV_NONE ?
5989 el_act2img(effective_element, effective_action) :
5990 el_act_dir2img(effective_element, effective_action,
5992 struct GraphicInfo *g = &graphic_info[graphic];
5993 struct GraphicInfo_EM *g_em = &graphic_info_em_player[p][i][7 - j];
5999 Bitmap *debug_bitmap = g_em->bitmap;
6000 int debug_src_x = g_em->src_x;
6001 int debug_src_y = g_em->src_y;
6004 int frame = getAnimationFrame(g->anim_frames,
6007 g->anim_start_frame,
6010 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x,&src_y, FALSE);
6012 g_em->bitmap = src_bitmap;
6013 g_em->src_x = src_x;
6014 g_em->src_y = src_y;
6015 g_em->src_offset_x = 0;
6016 g_em->src_offset_y = 0;
6017 g_em->dst_offset_x = 0;
6018 g_em->dst_offset_y = 0;
6019 g_em->width = TILEX;
6020 g_em->height = TILEY;
6023 if (g_em->bitmap != debug_bitmap ||
6024 g_em->src_x != debug_src_x ||
6025 g_em->src_y != debug_src_y)
6027 static int last_i = -1;
6035 printf("::: EMC GFX ERROR for p/a %d/%d -> %d ('%s', '%s', %d)",
6036 p, i, element, element_info[element].token_name,
6037 element_action_info[effective_action].suffix, direction);
6039 if (element != effective_element)
6040 printf(" [%d ('%s')]",
6042 element_info[effective_element].token_name);
6046 if (g_em->bitmap != debug_bitmap)
6047 printf(" %d: different bitmap! (0x%08x != 0x%08x)\n",
6048 j, (int)(g_em->bitmap), (int)(debug_bitmap));
6050 if (g_em->src_x != debug_src_x ||
6051 g_em->src_y != debug_src_y)
6052 printf(" frame %d: %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
6054 g_em->src_x, g_em->src_y,
6055 g_em->src_x / 32, g_em->src_y / 32,
6056 debug_src_x, debug_src_y,
6057 debug_src_x / 32, debug_src_y / 32);