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(" CustomValue: %d\n", CustomValue[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) ||
980 if (Feld[xx][yy] == EL_ELEMENT_SNAPPING)
984 element = TILE_GFX_ELEMENT(xx, yy);
986 if (!GFX_CRUMBLED(element))
989 if (!IN_LEV_FIELD(xx, yy) ||
990 !IN_SCR_FIELD(sxx, syy) ||
991 !GFX_CRUMBLED(Feld[xx][yy]) ||
997 graphic = el_act2crm(element, ACTION_DEFAULT);
999 graphic = el_act2crm(Feld[xx][yy], ACTION_DEFAULT);
1001 crumbled_border_size = graphic_info[graphic].border_size;
1003 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1005 if (i == 1 || i == 2)
1007 width = crumbled_border_size;
1009 cx = (i == 1 ? TILEX - crumbled_border_size : 0);
1015 height = crumbled_border_size;
1017 cy = (i == 0 ? TILEY - crumbled_border_size : 0);
1020 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1021 width, height, FX + sxx * TILEX + cx, FY + syy * TILEY + cy);
1023 MarkTileDirty(sxx, syy);
1028 void DrawLevelFieldCrumbledSand(int x, int y)
1032 if (!IN_LEV_FIELD(x, y))
1036 if (Feld[x][y] == EL_ELEMENT_SNAPPING &&
1037 GFX_CRUMBLED(GfxElement[x][y]))
1039 DrawLevelFieldCrumbledSandDigging(x, y, GfxDir[x][y], GfxFrame[x][y]);
1045 graphic = el_act2crm(TILE_GFX_ELEMENT(x, y), ACTION_DEFAULT);
1047 graphic = el_act2crm(Feld[x][y], ACTION_DEFAULT);
1050 DrawLevelFieldCrumbledSandExt(x, y, graphic, 0);
1053 void DrawLevelFieldCrumbledSandDigging(int x, int y, int direction,
1056 int graphic1 = el_act_dir2img(GfxElement[x][y], ACTION_DIGGING, direction);
1057 int graphic2 = el_act_dir2crm(GfxElement[x][y], ACTION_DIGGING, direction);
1058 int frame1 = getGraphicAnimationFrame(graphic1, step_frame);
1059 int frame2 = getGraphicAnimationFrame(graphic2, step_frame);
1060 int sx = SCREENX(x), sy = SCREENY(y);
1062 DrawGraphic(sx, sy, graphic1, frame1);
1063 DrawLevelFieldCrumbledSandExt(x, y, graphic2, frame2);
1066 void DrawLevelFieldCrumbledSandNeighbours(int x, int y)
1068 int sx = SCREENX(x), sy = SCREENY(y);
1069 static int xy[4][2] =
1078 for (i = 0; i < 4; i++)
1080 int xx = x + xy[i][0];
1081 int yy = y + xy[i][1];
1082 int sxx = sx + xy[i][0];
1083 int syy = sy + xy[i][1];
1085 if (!IN_LEV_FIELD(xx, yy) ||
1086 !IN_SCR_FIELD(sxx, syy) ||
1087 !GFX_CRUMBLED(Feld[xx][yy]) ||
1091 DrawLevelField(xx, yy);
1095 static int getBorderElement(int x, int y)
1099 { EL_STEELWALL_TOPLEFT, EL_INVISIBLE_STEELWALL_TOPLEFT },
1100 { EL_STEELWALL_TOPRIGHT, EL_INVISIBLE_STEELWALL_TOPRIGHT },
1101 { EL_STEELWALL_BOTTOMLEFT, EL_INVISIBLE_STEELWALL_BOTTOMLEFT },
1102 { EL_STEELWALL_BOTTOMRIGHT, EL_INVISIBLE_STEELWALL_BOTTOMRIGHT },
1103 { EL_STEELWALL_VERTICAL, EL_INVISIBLE_STEELWALL_VERTICAL },
1104 { EL_STEELWALL_HORIZONTAL, EL_INVISIBLE_STEELWALL_HORIZONTAL },
1105 { EL_STEELWALL, EL_INVISIBLE_STEELWALL }
1107 int steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
1108 int steel_position = (x == -1 && y == -1 ? 0 :
1109 x == lev_fieldx && y == -1 ? 1 :
1110 x == -1 && y == lev_fieldy ? 2 :
1111 x == lev_fieldx && y == lev_fieldy ? 3 :
1112 x == -1 || x == lev_fieldx ? 4 :
1113 y == -1 || y == lev_fieldy ? 5 : 6);
1115 return border[steel_position][steel_type];
1118 void DrawScreenElement(int x, int y, int element)
1120 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1121 DrawLevelFieldCrumbledSand(LEVELX(x), LEVELY(y));
1124 void DrawLevelElement(int x, int y, int element)
1126 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1127 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1130 void DrawScreenField(int x, int y)
1132 int lx = LEVELX(x), ly = LEVELY(y);
1133 int element, content;
1135 if (!IN_LEV_FIELD(lx, ly))
1137 if (lx < -1 || lx > lev_fieldx || ly < -1 || ly > lev_fieldy)
1140 element = getBorderElement(lx, ly);
1142 DrawScreenElement(x, y, element);
1146 element = Feld[lx][ly];
1147 content = Store[lx][ly];
1149 if (IS_MOVING(lx, ly))
1151 int horiz_move = (MovDir[lx][ly] == MV_LEFT || MovDir[lx][ly] == MV_RIGHT);
1152 boolean cut_mode = NO_CUTTING;
1154 if (element == EL_QUICKSAND_EMPTYING ||
1155 element == EL_MAGIC_WALL_EMPTYING ||
1156 element == EL_BD_MAGIC_WALL_EMPTYING ||
1157 element == EL_AMOEBA_DROPPING)
1158 cut_mode = CUT_ABOVE;
1159 else if (element == EL_QUICKSAND_FILLING ||
1160 element == EL_MAGIC_WALL_FILLING ||
1161 element == EL_BD_MAGIC_WALL_FILLING)
1162 cut_mode = CUT_BELOW;
1164 if (cut_mode == CUT_ABOVE)
1165 DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1167 DrawScreenElement(x, y, EL_EMPTY);
1170 DrawScreenElementShifted(x, y, MovPos[lx][ly], 0, element, NO_CUTTING);
1171 else if (cut_mode == NO_CUTTING)
1172 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], element, cut_mode);
1174 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], content, cut_mode);
1176 if (content == EL_ACID)
1178 int dir = MovDir[lx][ly];
1179 int newlx = lx + (dir == MV_LEFT ? -1 : dir == MV_RIGHT ? +1 : 0);
1180 int newly = ly + (dir == MV_UP ? -1 : dir == MV_DOWN ? +1 : 0);
1182 DrawLevelElementThruMask(newlx, newly, EL_ACID);
1185 else if (IS_BLOCKED(lx, ly))
1190 boolean cut_mode = NO_CUTTING;
1191 int element_old, content_old;
1193 Blocked2Moving(lx, ly, &oldx, &oldy);
1196 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1197 MovDir[oldx][oldy] == MV_RIGHT);
1199 element_old = Feld[oldx][oldy];
1200 content_old = Store[oldx][oldy];
1202 if (element_old == EL_QUICKSAND_EMPTYING ||
1203 element_old == EL_MAGIC_WALL_EMPTYING ||
1204 element_old == EL_BD_MAGIC_WALL_EMPTYING ||
1205 element_old == EL_AMOEBA_DROPPING)
1206 cut_mode = CUT_ABOVE;
1208 DrawScreenElement(x, y, EL_EMPTY);
1211 DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
1213 else if (cut_mode == NO_CUTTING)
1214 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
1217 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
1220 else if (IS_DRAWABLE(element))
1221 DrawScreenElement(x, y, element);
1223 DrawScreenElement(x, y, EL_EMPTY);
1226 void DrawLevelField(int x, int y)
1228 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1229 DrawScreenField(SCREENX(x), SCREENY(y));
1230 else if (IS_MOVING(x, y))
1234 Moving2Blocked(x, y, &newx, &newy);
1235 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1236 DrawScreenField(SCREENX(newx), SCREENY(newy));
1238 else if (IS_BLOCKED(x, y))
1242 Blocked2Moving(x, y, &oldx, &oldy);
1243 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1244 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1248 void DrawMiniElement(int x, int y, int element)
1252 graphic = el2edimg(element);
1253 DrawMiniGraphic(x, y, graphic);
1256 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1258 int x = sx + scroll_x, y = sy + scroll_y;
1260 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1261 DrawMiniElement(sx, sy, EL_EMPTY);
1262 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1263 DrawMiniElement(sx, sy, Feld[x][y]);
1265 DrawMiniGraphic(sx, sy, el2edimg(getBorderElement(x, y)));
1268 void DrawEnvelopeBackground(int envelope_nr, int startx, int starty,
1269 int x, int y, int xsize, int ysize, int font_nr)
1271 int font_width = getFontWidth(font_nr);
1272 int font_height = getFontHeight(font_nr);
1273 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1276 int dst_x = SX + startx + x * font_width;
1277 int dst_y = SY + starty + y * font_height;
1278 int width = graphic_info[graphic].width;
1279 int height = graphic_info[graphic].height;
1280 int inner_width = MAX(width - 2 * font_width, font_width);
1281 int inner_height = MAX(height - 2 * font_height, font_height);
1282 int inner_sx = (width >= 3 * font_width ? font_width : 0);
1283 int inner_sy = (height >= 3 * font_height ? font_height : 0);
1284 boolean draw_masked = graphic_info[graphic].draw_masked;
1286 getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
1288 if (src_bitmap == NULL || width < font_width || height < font_height)
1290 ClearRectangle(drawto, dst_x, dst_y, font_width, font_height);
1294 src_x += (x == 0 ? 0 : x == xsize - 1 ? width - font_width :
1295 inner_sx + (x - 1) * font_width % inner_width);
1296 src_y += (y == 0 ? 0 : y == ysize - 1 ? height - font_height :
1297 inner_sy + (y - 1) * font_height % inner_height);
1301 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1302 dst_x - src_x, dst_y - src_y);
1303 BlitBitmapMasked(src_bitmap, drawto, src_x, src_y, font_width, font_height,
1307 BlitBitmap(src_bitmap, drawto, src_x, src_y, font_width, font_height,
1311 void AnimateEnvelope(int envelope_nr, int anim_mode, int action)
1313 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1314 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
1315 int mask_mode = (src_bitmap != NULL ? BLIT_MASKED : BLIT_ON_BACKGROUND);
1316 boolean ffwd_delay = (tape.playing && tape.fast_forward);
1317 boolean no_delay = (tape.warp_forward);
1318 unsigned long anim_delay = 0;
1319 int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
1320 int anim_delay_value = (no_delay ? 0 : frame_delay_value);
1321 int font_nr = FONT_ENVELOPE_1 + envelope_nr;
1322 int font_width = getFontWidth(font_nr);
1323 int font_height = getFontHeight(font_nr);
1324 int max_xsize = level.envelope_xsize[envelope_nr];
1325 int max_ysize = level.envelope_ysize[envelope_nr];
1326 int xstart = (anim_mode & ANIM_VERTICAL ? max_xsize : 0);
1327 int ystart = (anim_mode & ANIM_HORIZONTAL ? max_ysize : 0);
1328 int xend = max_xsize;
1329 int yend = (anim_mode != ANIM_DEFAULT ? max_ysize : 0);
1330 int xstep = (xstart < xend ? 1 : 0);
1331 int ystep = (ystart < yend || xstep == 0 ? 1 : 0);
1334 for (x = xstart, y = ystart; x <= xend && y <= yend; x += xstep, y += ystep)
1336 int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2;
1337 int ysize = (action == ACTION_CLOSING ? yend - (y - ystart) : y) + 2;
1338 int sx = (SXSIZE - xsize * font_width) / 2;
1339 int sy = (SYSIZE - ysize * font_height) / 2;
1342 SetDrawtoField(DRAW_BUFFERED);
1344 BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
1346 SetDrawtoField(DRAW_BACKBUFFER);
1348 for (yy = 0; yy < ysize; yy++) for (xx = 0; xx < xsize; xx++)
1349 DrawEnvelopeBackground(envelope_nr, sx,sy, xx,yy, xsize, ysize, font_nr);
1351 DrawTextToTextArea(SX + sx + font_width, SY + sy + font_height,
1352 level.envelope_text[envelope_nr], font_nr, max_xsize,
1353 xsize - 2, ysize - 2, mask_mode);
1355 redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
1358 WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
1362 void ShowEnvelope(int envelope_nr)
1364 int element = EL_ENVELOPE_1 + envelope_nr;
1365 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1366 int sound_opening = element_info[element].sound[ACTION_OPENING];
1367 int sound_closing = element_info[element].sound[ACTION_CLOSING];
1368 boolean ffwd_delay = (tape.playing && tape.fast_forward);
1369 boolean no_delay = (tape.warp_forward);
1370 int normal_delay_value = ONE_SECOND_DELAY / (ffwd_delay ? 2 : 1);
1371 int wait_delay_value = (no_delay ? 0 : normal_delay_value);
1372 int anim_mode = graphic_info[graphic].anim_mode;
1373 int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL:
1374 anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode);
1376 game.envelope_active = TRUE; /* needed for RedrawPlayfield() events */
1378 PlaySoundStereo(sound_opening, SOUND_MIDDLE);
1380 if (anim_mode == ANIM_DEFAULT)
1381 AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_OPENING);
1383 AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_OPENING);
1386 Delay(wait_delay_value);
1388 WaitForEventToContinue();
1390 PlaySoundStereo(sound_closing, SOUND_MIDDLE);
1392 if (anim_mode != ANIM_NONE)
1393 AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_CLOSING);
1395 if (anim_mode == ANIM_DEFAULT)
1396 AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_CLOSING);
1398 game.envelope_active = FALSE;
1400 SetDrawtoField(DRAW_BUFFERED);
1402 redraw_mask |= REDRAW_FIELD;
1406 void getMicroGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1408 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
1409 int mini_startx = src_bitmap->width * 3 / 4;
1410 int mini_starty = src_bitmap->height * 2 / 3;
1411 int src_x = mini_startx + graphic_info[graphic].src_x / 8;
1412 int src_y = mini_starty + graphic_info[graphic].src_y / 8;
1414 *bitmap = src_bitmap;
1419 void DrawMicroElement(int xpos, int ypos, int element)
1423 int graphic = el2preimg(element);
1425 getMicroGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1426 BlitBitmap(src_bitmap, drawto, src_x, src_y, MICRO_TILEX, MICRO_TILEY,
1434 SetDrawBackgroundMask(REDRAW_NONE);
1437 for (x = BX1; x <= BX2; x++)
1438 for (y = BY1; y <= BY2; y++)
1439 DrawScreenField(x, y);
1441 redraw_mask |= REDRAW_FIELD;
1444 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1448 for (x = 0; x < size_x; x++)
1449 for (y = 0; y < size_y; y++)
1450 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1452 redraw_mask |= REDRAW_FIELD;
1455 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1459 DrawBackground(xpos, ypos, MICROLEVEL_XSIZE, MICROLEVEL_YSIZE);
1461 if (lev_fieldx < STD_LEV_FIELDX)
1462 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1463 if (lev_fieldy < STD_LEV_FIELDY)
1464 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1466 xpos += MICRO_TILEX;
1467 ypos += MICRO_TILEY;
1469 for (x = -1; x <= STD_LEV_FIELDX; x++)
1471 for (y = -1; y <= STD_LEV_FIELDY; y++)
1473 int lx = from_x + x, ly = from_y + y;
1475 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1476 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1477 level.field[lx][ly]);
1478 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1
1479 && BorderElement != EL_EMPTY)
1480 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1481 getBorderElement(lx, ly));
1485 redraw_mask |= REDRAW_MICROLEVEL;
1488 #define MICROLABEL_EMPTY 0
1489 #define MICROLABEL_LEVEL_NAME 1
1490 #define MICROLABEL_LEVEL_AUTHOR_HEAD 2
1491 #define MICROLABEL_LEVEL_AUTHOR 3
1492 #define MICROLABEL_IMPORTED_FROM_HEAD 4
1493 #define MICROLABEL_IMPORTED_FROM 5
1494 #define MICROLABEL_IMPORTED_BY_HEAD 6
1495 #define MICROLABEL_IMPORTED_BY 7
1497 static void DrawMicroLevelLabelExt(int mode)
1499 char label_text[MAX_OUTPUT_LINESIZE + 1];
1500 int max_len_label_text;
1501 int font_nr = FONT_TEXT_2;
1504 if (mode == MICROLABEL_LEVEL_AUTHOR_HEAD ||
1505 mode == MICROLABEL_IMPORTED_FROM_HEAD ||
1506 mode == MICROLABEL_IMPORTED_BY_HEAD)
1507 font_nr = FONT_TEXT_3;
1509 max_len_label_text = SXSIZE / getFontWidth(font_nr);
1511 for (i = 0; i < max_len_label_text; i++)
1512 label_text[i] = ' ';
1513 label_text[max_len_label_text] = '\0';
1515 if (strlen(label_text) > 0)
1517 int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
1518 int lypos = MICROLABEL2_YPOS;
1520 DrawText(lxpos, lypos, label_text, font_nr);
1524 (mode == MICROLABEL_LEVEL_NAME ? level.name :
1525 mode == MICROLABEL_LEVEL_AUTHOR_HEAD ? "created by" :
1526 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
1527 mode == MICROLABEL_IMPORTED_FROM_HEAD ? "imported from" :
1528 mode == MICROLABEL_IMPORTED_FROM ? leveldir_current->imported_from :
1529 mode == MICROLABEL_IMPORTED_BY_HEAD ? "imported by" :
1530 mode == MICROLABEL_IMPORTED_BY ? leveldir_current->imported_by :""),
1531 max_len_label_text);
1532 label_text[max_len_label_text] = '\0';
1534 if (strlen(label_text) > 0)
1536 int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
1537 int lypos = MICROLABEL2_YPOS;
1539 DrawText(lxpos, lypos, label_text, font_nr);
1542 redraw_mask |= REDRAW_MICROLEVEL;
1545 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1547 static unsigned long scroll_delay = 0;
1548 static unsigned long label_delay = 0;
1549 static int from_x, from_y, scroll_direction;
1550 static int label_state, label_counter;
1551 int last_game_status = game_status; /* save current game status */
1553 /* force PREVIEW font on preview level */
1554 game_status = GAME_MODE_PSEUDO_PREVIEW;
1558 from_x = from_y = 0;
1559 scroll_direction = MV_RIGHT;
1563 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1564 DrawMicroLevelLabelExt(label_state);
1566 /* initialize delay counters */
1567 DelayReached(&scroll_delay, 0);
1568 DelayReached(&label_delay, 0);
1570 if (leveldir_current->name)
1572 char label_text[MAX_OUTPUT_LINESIZE + 1];
1573 int font_nr = FONT_TEXT_1;
1574 int max_len_label_text = SXSIZE / getFontWidth(font_nr);
1577 strncpy(label_text, leveldir_current->name, max_len_label_text);
1578 label_text[max_len_label_text] = '\0';
1580 lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
1581 lypos = SY + MICROLABEL1_YPOS;
1583 DrawText(lxpos, lypos, label_text, font_nr);
1586 game_status = last_game_status; /* restore current game status */
1591 /* scroll micro level, if needed */
1592 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1593 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1595 switch (scroll_direction)
1601 scroll_direction = MV_UP;
1605 if (from_x < lev_fieldx - STD_LEV_FIELDX)
1608 scroll_direction = MV_DOWN;
1615 scroll_direction = MV_RIGHT;
1619 if (from_y < lev_fieldy - STD_LEV_FIELDY)
1622 scroll_direction = MV_LEFT;
1629 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1632 /* !!! THIS ALL SUCKS -- SHOULD BE CLEANLY REWRITTEN !!! */
1633 /* redraw micro level label, if needed */
1634 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1635 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1636 strcmp(level.author, leveldir_current->name) != 0 &&
1637 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1639 int max_label_counter = 23;
1641 if (leveldir_current->imported_from != NULL &&
1642 strlen(leveldir_current->imported_from) > 0)
1643 max_label_counter += 14;
1644 if (leveldir_current->imported_by != NULL &&
1645 strlen(leveldir_current->imported_by) > 0)
1646 max_label_counter += 14;
1648 label_counter = (label_counter + 1) % max_label_counter;
1649 label_state = (label_counter >= 0 && label_counter <= 7 ?
1650 MICROLABEL_LEVEL_NAME :
1651 label_counter >= 9 && label_counter <= 12 ?
1652 MICROLABEL_LEVEL_AUTHOR_HEAD :
1653 label_counter >= 14 && label_counter <= 21 ?
1654 MICROLABEL_LEVEL_AUTHOR :
1655 label_counter >= 23 && label_counter <= 26 ?
1656 MICROLABEL_IMPORTED_FROM_HEAD :
1657 label_counter >= 28 && label_counter <= 35 ?
1658 MICROLABEL_IMPORTED_FROM :
1659 label_counter >= 37 && label_counter <= 40 ?
1660 MICROLABEL_IMPORTED_BY_HEAD :
1661 label_counter >= 42 && label_counter <= 49 ?
1662 MICROLABEL_IMPORTED_BY : MICROLABEL_EMPTY);
1664 if (leveldir_current->imported_from == NULL &&
1665 (label_state == MICROLABEL_IMPORTED_FROM_HEAD ||
1666 label_state == MICROLABEL_IMPORTED_FROM))
1667 label_state = (label_state == MICROLABEL_IMPORTED_FROM_HEAD ?
1668 MICROLABEL_IMPORTED_BY_HEAD : MICROLABEL_IMPORTED_BY);
1670 DrawMicroLevelLabelExt(label_state);
1673 game_status = last_game_status; /* restore current game status */
1676 inline void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
1677 int graphic, int sync_frame, int mask_mode)
1679 int frame = getGraphicAnimationFrame(graphic, sync_frame);
1681 if (mask_mode == USE_MASKING)
1682 DrawGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
1684 DrawGraphicExt(dst_bitmap, x, y, graphic, frame);
1687 inline void DrawGraphicAnimation(int x, int y, int graphic)
1689 int lx = LEVELX(x), ly = LEVELY(y);
1691 if (!IN_SCR_FIELD(x, y))
1694 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
1695 graphic, GfxFrame[lx][ly], NO_MASKING);
1696 MarkTileDirty(x, y);
1699 void DrawLevelGraphicAnimation(int x, int y, int graphic)
1701 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
1704 void DrawLevelElementAnimation(int x, int y, int element)
1706 int graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
1708 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
1711 inline void DrawLevelGraphicAnimationIfNeeded(int x, int y, int graphic)
1713 int sx = SCREENX(x), sy = SCREENY(y);
1715 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
1718 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
1721 DrawGraphicAnimation(sx, sy, graphic);
1724 if (GFX_CRUMBLED(TILE_GFX_ELEMENT(x, y)))
1725 DrawLevelFieldCrumbledSand(x, y);
1727 if (GFX_CRUMBLED(Feld[x][y]))
1728 DrawLevelFieldCrumbledSand(x, y);
1732 void DrawLevelElementAnimationIfNeeded(int x, int y, int element)
1734 int sx = SCREENX(x), sy = SCREENY(y);
1737 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
1740 graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
1742 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
1745 DrawGraphicAnimation(sx, sy, graphic);
1747 if (GFX_CRUMBLED(element))
1748 DrawLevelFieldCrumbledSand(x, y);
1751 static int getPlayerGraphic(struct PlayerInfo *player, int move_dir)
1753 if (player->use_murphy_graphic)
1755 /* this works only because currently only one player can be "murphy" ... */
1756 static int last_horizontal_dir = MV_LEFT;
1757 int graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, move_dir);
1759 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
1760 last_horizontal_dir = move_dir;
1762 if (graphic == IMG_SP_MURPHY) /* undefined => use special graphic */
1764 int direction = (player->is_snapping ? move_dir : last_horizontal_dir);
1766 graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, direction);
1772 return el_act_dir2img(player->element_nr, player->GfxAction, move_dir);
1775 static boolean equalGraphics(int graphic1, int graphic2)
1777 struct GraphicInfo *g1 = &graphic_info[graphic1];
1778 struct GraphicInfo *g2 = &graphic_info[graphic2];
1780 return (g1->bitmap == g2->bitmap &&
1781 g1->src_x == g2->src_x &&
1782 g1->src_y == g2->src_y &&
1783 g1->anim_frames == g2->anim_frames &&
1784 g1->anim_delay == g2->anim_delay &&
1785 g1->anim_mode == g2->anim_mode);
1788 void DrawAllPlayers()
1792 for (i = 0; i < MAX_PLAYERS; i++)
1793 if (stored_player[i].active)
1794 DrawPlayer(&stored_player[i]);
1797 void DrawPlayerField(int x, int y)
1799 if (!IS_PLAYER(x, y))
1802 DrawPlayer(PLAYERINFO(x, y));
1805 void DrawPlayer(struct PlayerInfo *player)
1807 int jx = player->jx;
1808 int jy = player->jy;
1809 int move_dir = player->MovDir;
1810 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? +1 : 0);
1811 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? +1 : 0);
1812 int last_jx = (player->is_moving ? jx - dx : jx);
1813 int last_jy = (player->is_moving ? jy - dy : jy);
1814 int next_jx = jx + dx;
1815 int next_jy = jy + dy;
1816 boolean player_is_moving = (player->MovPos ? TRUE : FALSE);
1817 int sx = SCREENX(jx), sy = SCREENY(jy);
1818 int sxx = 0, syy = 0;
1819 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
1821 int action = ACTION_DEFAULT;
1822 int last_player_graphic = getPlayerGraphic(player, move_dir);
1823 int last_player_frame = player->Frame;
1826 if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
1830 if (!IN_LEV_FIELD(jx, jy))
1832 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
1833 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
1834 printf("DrawPlayerField(): This should never happen!\n");
1839 if (element == EL_EXPLOSION)
1842 action = (player->is_pushing ? ACTION_PUSHING :
1843 player->is_digging ? ACTION_DIGGING :
1844 player->is_collecting ? ACTION_COLLECTING :
1845 player->is_moving ? ACTION_MOVING :
1846 player->is_snapping ? ACTION_SNAPPING :
1847 player->is_dropping ? ACTION_DROPPING :
1848 player->is_waiting ? player->action_waiting : ACTION_DEFAULT);
1850 InitPlayerGfxAnimation(player, action, move_dir);
1852 /* ----------------------------------------------------------------------- */
1853 /* draw things in the field the player is leaving, if needed */
1854 /* ----------------------------------------------------------------------- */
1856 if (player->is_moving)
1858 if (Back[last_jx][last_jy] && IS_DRAWABLE(last_element))
1860 DrawLevelElement(last_jx, last_jy, Back[last_jx][last_jy]);
1862 if (last_element == EL_DYNAMITE_ACTIVE ||
1863 last_element == EL_SP_DISK_RED_ACTIVE)
1864 DrawDynamite(last_jx, last_jy);
1866 DrawLevelFieldThruMask(last_jx, last_jy);
1868 else if (last_element == EL_DYNAMITE_ACTIVE ||
1869 last_element == EL_SP_DISK_RED_ACTIVE)
1870 DrawDynamite(last_jx, last_jy);
1872 DrawLevelField(last_jx, last_jy);
1874 if (player->is_pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
1875 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
1878 if (!IN_SCR_FIELD(sx, sy))
1881 if (setup.direct_draw)
1882 SetDrawtoField(DRAW_BUFFERED);
1884 /* ----------------------------------------------------------------------- */
1885 /* draw things behind the player, if needed */
1886 /* ----------------------------------------------------------------------- */
1889 DrawLevelElement(jx, jy, Back[jx][jy]);
1890 else if (IS_ACTIVE_BOMB(element))
1891 DrawLevelElement(jx, jy, EL_EMPTY);
1894 if (player_is_moving && GfxElement[jx][jy] != EL_UNDEFINED)
1896 if (GFX_CRUMBLED(GfxElement[jx][jy]))
1897 DrawLevelFieldCrumbledSandDigging(jx, jy, move_dir, player->StepFrame);
1900 int old_element = GfxElement[jx][jy];
1901 int old_graphic = el_act_dir2img(old_element, action, move_dir);
1902 int frame = getGraphicAnimationFrame(old_graphic, player->StepFrame);
1904 DrawGraphic(sx, sy, old_graphic, frame);
1909 GfxElement[jx][jy] = EL_UNDEFINED;
1911 /* make sure that pushed elements are drawn with correct frame rate */
1912 if (player->is_pushing && player->is_moving)
1913 GfxFrame[jx][jy] = player->StepFrame;
1915 DrawLevelField(jx, jy);
1919 /* ----------------------------------------------------------------------- */
1920 /* draw player himself */
1921 /* ----------------------------------------------------------------------- */
1923 graphic = getPlayerGraphic(player, move_dir);
1925 /* in the case of changed player action or direction, prevent the current
1926 animation frame from being restarted for identical animations */
1927 if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic))
1928 player->Frame = last_player_frame;
1930 frame = getGraphicAnimationFrame(graphic, player->Frame);
1934 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
1935 sxx = player->GfxPos;
1937 syy = player->GfxPos;
1940 if (!setup.soft_scrolling && ScreenMovPos)
1943 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
1945 if (SHIELD_ON(player))
1947 int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
1948 IMG_SHIELD_NORMAL_ACTIVE);
1949 int frame = getGraphicAnimationFrame(graphic, -1);
1951 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
1954 /* ----------------------------------------------------------------------- */
1955 /* draw things the player is pushing, if needed */
1956 /* ----------------------------------------------------------------------- */
1959 printf("::: %d, %d [%d, %d] [%d]\n",
1960 player->is_pushing, player_is_moving, player->GfxAction,
1961 player->is_moving, player_is_moving);
1965 if (player->is_pushing && player->is_moving)
1967 int px = SCREENX(jx), py = SCREENY(jy);
1968 int pxx = (TILEX - ABS(sxx)) * dx;
1969 int pyy = (TILEY - ABS(syy)) * dy;
1974 if (!IS_MOVING(jx, jy)) /* push movement already finished */
1975 element = Feld[next_jx][next_jy];
1977 graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
1978 frame = getGraphicAnimationFrame(graphic, player->StepFrame);
1980 /* draw background element under pushed element (like the Sokoban field) */
1981 if (Back[next_jx][next_jy])
1982 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
1984 /* masked drawing is needed for EMC style (double) movement graphics */
1985 DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame, NO_CUTTING);
1989 /* ----------------------------------------------------------------------- */
1990 /* draw things in front of player (active dynamite or dynabombs) */
1991 /* ----------------------------------------------------------------------- */
1993 if (IS_ACTIVE_BOMB(element))
1995 graphic = el2img(element);
1996 frame = getGraphicAnimationFrame(graphic, GfxFrame[jx][jy]);
1998 if (game.emulation == EMU_SUPAPLEX)
1999 DrawGraphic(sx, sy, IMG_SP_DISK_RED, frame);
2001 DrawGraphicThruMask(sx, sy, graphic, frame);
2004 if (player_is_moving && last_element == EL_EXPLOSION)
2006 int graphic = el_act2img(GfxElement[last_jx][last_jy], ACTION_EXPLODING);
2007 int delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2);
2008 int phase = ExplodePhase[last_jx][last_jy] - 1;
2009 int frame = getGraphicAnimationFrame(graphic, phase - delay);
2012 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy), graphic, frame);
2015 /* ----------------------------------------------------------------------- */
2016 /* draw elements the player is just walking/passing through/under */
2017 /* ----------------------------------------------------------------------- */
2019 if (player_is_moving)
2021 /* handle the field the player is leaving ... */
2022 if (IS_ACCESSIBLE_INSIDE(last_element))
2023 DrawLevelField(last_jx, last_jy);
2024 else if (IS_ACCESSIBLE_UNDER(last_element))
2025 DrawLevelFieldThruMask(last_jx, last_jy);
2028 /* do not redraw accessible elements if the player is just pushing them */
2029 if (!player_is_moving || !player->is_pushing)
2031 /* ... and the field the player is entering */
2032 if (IS_ACCESSIBLE_INSIDE(element))
2033 DrawLevelField(jx, jy);
2034 else if (IS_ACCESSIBLE_UNDER(element))
2035 DrawLevelFieldThruMask(jx, jy);
2038 if (setup.direct_draw)
2040 int dst_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
2041 int dst_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
2042 int x_size = TILEX * (1 + ABS(jx - last_jx));
2043 int y_size = TILEY * (1 + ABS(jy - last_jy));
2045 BlitBitmap(drawto_field, window,
2046 dst_x, dst_y, x_size, y_size, dst_x, dst_y);
2047 SetDrawtoField(DRAW_DIRECT);
2050 MarkTileDirty(sx, sy);
2053 /* ------------------------------------------------------------------------- */
2055 void WaitForEventToContinue()
2057 boolean still_wait = TRUE;
2059 /* simulate releasing mouse button over last gadget, if still pressed */
2061 HandleGadgets(-1, -1, 0);
2063 button_status = MB_RELEASED;
2075 case EVENT_BUTTONPRESS:
2076 case EVENT_KEYPRESS:
2080 case EVENT_KEYRELEASE:
2081 ClearPlayerAction();
2085 HandleOtherEvents(&event);
2089 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2096 /* don't eat all CPU time */
2101 #define MAX_REQUEST_LINES 13
2102 #define MAX_REQUEST_LINE_FONT1_LEN 7
2103 #define MAX_REQUEST_LINE_FONT2_LEN 10
2105 boolean Request(char *text, unsigned int req_state)
2107 int mx, my, ty, result = -1;
2108 unsigned int old_door_state;
2109 int last_game_status = game_status; /* save current game status */
2110 int max_request_line_len = MAX_REQUEST_LINE_FONT1_LEN;
2111 int font_nr = FONT_TEXT_2;
2112 int max_word_len = 0;
2115 for (text_ptr = text; *text_ptr; text_ptr++)
2117 max_word_len = (*text_ptr != ' ' ? max_word_len + 1 : 0);
2119 if (max_word_len > MAX_REQUEST_LINE_FONT1_LEN)
2121 max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
2122 font_nr = FONT_LEVEL_NUMBER;
2128 if (game_status == GAME_MODE_PLAYING &&
2129 level.game_engine_type == GAME_ENGINE_TYPE_EM)
2130 BlitScreenToBitmap_EM(backbuffer);
2132 /* disable deactivated drawing when quick-loading level tape recording */
2133 if (tape.playing && tape.deactivate_display)
2134 TapeDeactivateDisplayOff(TRUE);
2136 SetMouseCursor(CURSOR_DEFAULT);
2138 #if defined(NETWORK_AVALIABLE)
2139 /* pause network game while waiting for request to answer */
2140 if (options.network &&
2141 game_status == GAME_MODE_PLAYING &&
2142 req_state & REQUEST_WAIT_FOR_INPUT)
2143 SendToServer_PausePlaying();
2146 old_door_state = GetDoorState();
2148 /* simulate releasing mouse button over last gadget, if still pressed */
2150 HandleGadgets(-1, -1, 0);
2154 if (old_door_state & DOOR_OPEN_1)
2156 CloseDoor(DOOR_CLOSE_1);
2158 /* save old door content */
2159 BlitBitmap(bitmap_db_door, bitmap_db_door,
2160 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
2161 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
2164 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
2166 /* clear door drawing field */
2167 DrawBackground(DX, DY, DXSIZE, DYSIZE);
2169 /* force DOOR font on preview level */
2170 game_status = GAME_MODE_PSEUDO_DOOR;
2172 /* write text for request */
2173 for (ty = 0; ty < MAX_REQUEST_LINES; ty++)
2175 char text_line[max_request_line_len + 1];
2181 for (tl = 0, tx = 0; tx < max_request_line_len; tl++, tx++)
2184 if (!tc || tc == ' ')
2195 strncpy(text_line, text, tl);
2198 DrawText(DX + (DXSIZE - tl * getFontWidth(font_nr)) / 2,
2199 DY + 8 + ty * (getFontHeight(font_nr) + 2),
2200 text_line, font_nr);
2202 text += tl + (tc == ' ' ? 1 : 0);
2205 game_status = last_game_status; /* restore current game status */
2207 if (req_state & REQ_ASK)
2209 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
2210 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
2212 else if (req_state & REQ_CONFIRM)
2214 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
2216 else if (req_state & REQ_PLAYER)
2218 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
2219 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
2220 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
2221 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
2224 /* copy request gadgets to door backbuffer */
2225 BlitBitmap(drawto, bitmap_db_door,
2226 DX, DY, DXSIZE, DYSIZE,
2227 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2229 OpenDoor(DOOR_OPEN_1);
2231 if (!(req_state & REQUEST_WAIT_FOR_INPUT))
2233 SetDrawBackgroundMask(REDRAW_FIELD);
2238 if (game_status != GAME_MODE_MAIN)
2241 button_status = MB_RELEASED;
2243 request_gadget_id = -1;
2245 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
2257 case EVENT_BUTTONPRESS:
2258 case EVENT_BUTTONRELEASE:
2259 case EVENT_MOTIONNOTIFY:
2261 if (event.type == EVENT_MOTIONNOTIFY)
2263 if (!PointerInWindow(window))
2264 continue; /* window and pointer are on different screens */
2269 motion_status = TRUE;
2270 mx = ((MotionEvent *) &event)->x;
2271 my = ((MotionEvent *) &event)->y;
2275 motion_status = FALSE;
2276 mx = ((ButtonEvent *) &event)->x;
2277 my = ((ButtonEvent *) &event)->y;
2278 if (event.type == EVENT_BUTTONPRESS)
2279 button_status = ((ButtonEvent *) &event)->button;
2281 button_status = MB_RELEASED;
2284 /* this sets 'request_gadget_id' */
2285 HandleGadgets(mx, my, button_status);
2287 switch(request_gadget_id)
2289 case TOOL_CTRL_ID_YES:
2292 case TOOL_CTRL_ID_NO:
2295 case TOOL_CTRL_ID_CONFIRM:
2296 result = TRUE | FALSE;
2299 case TOOL_CTRL_ID_PLAYER_1:
2302 case TOOL_CTRL_ID_PLAYER_2:
2305 case TOOL_CTRL_ID_PLAYER_3:
2308 case TOOL_CTRL_ID_PLAYER_4:
2319 case EVENT_KEYPRESS:
2320 switch(GetEventKey((KeyEvent *)&event, TRUE))
2333 if (req_state & REQ_PLAYER)
2337 case EVENT_KEYRELEASE:
2338 ClearPlayerAction();
2342 HandleOtherEvents(&event);
2346 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2348 int joy = AnyJoystick();
2350 if (joy & JOY_BUTTON_1)
2352 else if (joy & JOY_BUTTON_2)
2358 /* don't eat all CPU time */
2362 if (game_status != GAME_MODE_MAIN)
2367 if (!(req_state & REQ_STAY_OPEN))
2369 CloseDoor(DOOR_CLOSE_1);
2371 if (((old_door_state & DOOR_OPEN_1) && !(req_state & REQ_STAY_CLOSED)) ||
2372 (req_state & REQ_REOPEN))
2373 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
2378 SetDrawBackgroundMask(REDRAW_FIELD);
2380 #if defined(NETWORK_AVALIABLE)
2381 /* continue network game after request */
2382 if (options.network &&
2383 game_status == GAME_MODE_PLAYING &&
2384 req_state & REQUEST_WAIT_FOR_INPUT)
2385 SendToServer_ContinuePlaying();
2388 /* restore deactivated drawing when quick-loading level tape recording */
2389 if (tape.playing && tape.deactivate_display)
2390 TapeDeactivateDisplayOn();
2395 unsigned int OpenDoor(unsigned int door_state)
2397 if (door_state & DOOR_COPY_BACK)
2399 if (door_state & DOOR_OPEN_1)
2400 BlitBitmap(bitmap_db_door, bitmap_db_door,
2401 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
2402 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2404 if (door_state & DOOR_OPEN_2)
2405 BlitBitmap(bitmap_db_door, bitmap_db_door,
2406 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY2, VXSIZE, VYSIZE,
2407 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2409 door_state &= ~DOOR_COPY_BACK;
2412 return MoveDoor(door_state);
2415 unsigned int CloseDoor(unsigned int door_state)
2417 unsigned int old_door_state = GetDoorState();
2419 if (!(door_state & DOOR_NO_COPY_BACK))
2421 if (old_door_state & DOOR_OPEN_1)
2422 BlitBitmap(backbuffer, bitmap_db_door,
2423 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2425 if (old_door_state & DOOR_OPEN_2)
2426 BlitBitmap(backbuffer, bitmap_db_door,
2427 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2429 door_state &= ~DOOR_NO_COPY_BACK;
2432 return MoveDoor(door_state);
2435 unsigned int GetDoorState()
2437 return MoveDoor(DOOR_GET_STATE);
2440 unsigned int SetDoorState(unsigned int door_state)
2442 return MoveDoor(door_state | DOOR_SET_STATE);
2445 unsigned int MoveDoor(unsigned int door_state)
2447 static int door1 = DOOR_OPEN_1;
2448 static int door2 = DOOR_CLOSE_2;
2449 unsigned long door_delay = 0;
2450 unsigned long door_delay_value;
2453 if (door_state == DOOR_GET_STATE)
2454 return(door1 | door2);
2456 if (door_state & DOOR_SET_STATE)
2458 if (door_state & DOOR_ACTION_1)
2459 door1 = door_state & DOOR_ACTION_1;
2460 if (door_state & DOOR_ACTION_2)
2461 door2 = door_state & DOOR_ACTION_2;
2463 return(door1 | door2);
2466 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2467 door_state &= ~DOOR_OPEN_1;
2468 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2469 door_state &= ~DOOR_CLOSE_1;
2470 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2471 door_state &= ~DOOR_OPEN_2;
2472 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2473 door_state &= ~DOOR_CLOSE_2;
2475 door_delay_value = (door_state & DOOR_ACTION_1 ? door_1.step_delay :
2478 if (setup.quick_doors)
2480 stepsize = 20; /* must be choosen to always draw last frame */
2481 door_delay_value = 0;
2484 if (global.autoplay_leveldir)
2486 door_state |= DOOR_NO_DELAY;
2487 door_state &= ~DOOR_CLOSE_ALL;
2490 if (door_state & DOOR_ACTION)
2492 boolean door_1_done = !(door_state & DOOR_ACTION_1);
2493 boolean door_2_done = !(door_state & DOOR_ACTION_2);
2494 int start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2495 int end = (door_state & DOOR_ACTION_1 &&
2496 door_1.anim_mode == ANIM_VERTICAL ? DYSIZE : DXSIZE);
2499 if (!(door_state & DOOR_NO_DELAY) && !setup.quick_doors)
2501 /* opening door sound has priority over simultaneously closing door */
2502 if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
2503 PlaySoundStereo(SND_DOOR_OPENING, SOUND_MIDDLE);
2504 else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
2505 PlaySoundStereo(SND_DOOR_CLOSING, SOUND_MIDDLE);
2508 for (x = start; x <= end && !(door_1_done && door_2_done); x += stepsize)
2510 Bitmap *bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2511 GC gc = bitmap->stored_clip_gc;
2513 if (door_state & DOOR_ACTION_1)
2515 int a = MIN(x * door_1.step_offset, end);
2516 int i = (door_state & DOOR_OPEN_1 ? end - a : a);
2520 BlitBitmap(bitmap_db_door, drawto,
2521 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i / 2,
2522 DXSIZE, DYSIZE - i / 2, DX, DY);
2524 ClearRectangle(drawto, DX, DY + DYSIZE - i / 2, DXSIZE, i / 2);
2527 if (door_1.anim_mode == ANIM_HORIZONTAL && x <= DXSIZE)
2529 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
2530 int dst1_x = DX + DXSIZE - i, dst1_y = DY;
2531 int src2_x = DXSIZE - i, src2_y = DOOR_GFX_PAGEY1;
2532 int dst2_x = DX, dst2_y = DY;
2533 int width = i, height = DYSIZE;
2535 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2536 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2539 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2540 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2543 else if (door_1.anim_mode == ANIM_VERTICAL && x <= DYSIZE)
2545 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
2546 int dst1_x = DX, dst1_y = DY + DYSIZE - i;
2547 int src2_x = 0, src2_y = DOOR_GFX_PAGEY1 + DYSIZE - i;
2548 int dst2_x = DX, dst2_y = DY;
2549 int width = DXSIZE, height = i;
2551 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2552 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2555 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2556 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2559 else if (x <= DXSIZE) /* ANIM_DEFAULT */
2561 int j = (door_1.anim_mode == ANIM_DEFAULT ? (DXSIZE - i) / 3 : 0);
2563 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2564 BlitBitmapMasked(bitmap, drawto,
2565 DXSIZE, DOOR_GFX_PAGEY1, i, 77,
2566 DX + DXSIZE - i, DY + j);
2567 BlitBitmapMasked(bitmap, drawto,
2568 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
2569 DX + DXSIZE - i, DY + 140 + j);
2570 SetClipOrigin(bitmap, gc, DX - DXSIZE + i,
2571 DY - (DOOR_GFX_PAGEY1 + j));
2572 BlitBitmapMasked(bitmap, drawto,
2573 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
2575 BlitBitmapMasked(bitmap, drawto,
2576 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
2579 BlitBitmapMasked(bitmap, drawto,
2580 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2582 BlitBitmapMasked(bitmap, drawto,
2583 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2585 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2586 BlitBitmapMasked(bitmap, drawto,
2587 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2588 DX + DXSIZE - i, DY + 77 + j);
2589 BlitBitmapMasked(bitmap, drawto,
2590 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2591 DX + DXSIZE - i, DY + 203 + j);
2594 redraw_mask |= REDRAW_DOOR_1;
2595 door_1_done = (a == end);
2598 if (door_state & DOOR_ACTION_2)
2600 int a = MIN(x * door_2.step_offset, VXSIZE);
2601 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - a : a);
2605 BlitBitmap(bitmap_db_door, drawto,
2606 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i / 2,
2607 VXSIZE, VYSIZE - i / 2, VX, VY);
2609 ClearRectangle(drawto, VX, VY + VYSIZE - i / 2, VXSIZE, i / 2);
2612 if (door_2.anim_mode == ANIM_HORIZONTAL && x <= VXSIZE)
2614 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
2615 int dst1_x = VX + VXSIZE - i, dst1_y = VY;
2616 int src2_x = VXSIZE - i, src2_y = DOOR_GFX_PAGEY2;
2617 int dst2_x = VX, dst2_y = VY;
2618 int width = i, height = VYSIZE;
2620 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2621 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2624 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2625 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2628 else if (door_2.anim_mode == ANIM_VERTICAL && x <= VYSIZE)
2630 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
2631 int dst1_x = VX, dst1_y = VY + VYSIZE - i;
2632 int src2_x = 0, src2_y = DOOR_GFX_PAGEY2 + VYSIZE - i;
2633 int dst2_x = VX, dst2_y = VY;
2634 int width = VXSIZE, height = i;
2636 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2637 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2640 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2641 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2644 else if (x <= VXSIZE) /* ANIM_DEFAULT */
2646 int j = (door_2.anim_mode == ANIM_DEFAULT ? (VXSIZE - i) / 3 : 0);
2648 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2649 BlitBitmapMasked(bitmap, drawto,
2650 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
2651 VX + VXSIZE - i, VY + j);
2652 SetClipOrigin(bitmap, gc,
2653 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2654 BlitBitmapMasked(bitmap, drawto,
2655 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
2658 BlitBitmapMasked(bitmap, drawto,
2659 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2660 i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
2661 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2662 BlitBitmapMasked(bitmap, drawto,
2663 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2665 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2668 redraw_mask |= REDRAW_DOOR_2;
2669 door_2_done = (a == VXSIZE);
2674 if (game_status == GAME_MODE_MAIN)
2677 if (!(door_state & DOOR_NO_DELAY))
2678 WaitUntilDelayReached(&door_delay, door_delay_value);
2682 if (door_state & DOOR_ACTION_1)
2683 door1 = door_state & DOOR_ACTION_1;
2684 if (door_state & DOOR_ACTION_2)
2685 door2 = door_state & DOOR_ACTION_2;
2687 return (door1 | door2);
2690 void DrawSpecialEditorDoor()
2692 /* draw bigger toolbox window */
2693 BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
2694 DOOR_GFX_PAGEX7, 0, EXSIZE + 8, 8,
2696 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2697 EX - 4, VY - 4, EXSIZE + 8, EYSIZE - VYSIZE + 4,
2700 redraw_mask |= REDRAW_ALL;
2703 void UndrawSpecialEditorDoor()
2705 /* draw normal tape recorder window */
2706 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2707 EX - 4, EY - 12, EXSIZE + 8, EYSIZE - VYSIZE + 12,
2710 redraw_mask |= REDRAW_ALL;
2714 /* ---------- new tool button stuff ---------------------------------------- */
2716 /* graphic position values for tool buttons */
2717 #define TOOL_BUTTON_YES_XPOS 2
2718 #define TOOL_BUTTON_YES_YPOS 250
2719 #define TOOL_BUTTON_YES_GFX_YPOS 0
2720 #define TOOL_BUTTON_YES_XSIZE 46
2721 #define TOOL_BUTTON_YES_YSIZE 28
2722 #define TOOL_BUTTON_NO_XPOS 52
2723 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2724 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2725 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2726 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2727 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2728 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2729 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2730 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2731 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2732 #define TOOL_BUTTON_PLAYER_XSIZE 30
2733 #define TOOL_BUTTON_PLAYER_YSIZE 30
2734 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2735 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2736 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2737 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2738 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2739 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2740 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2741 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2742 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2743 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2744 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2745 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2746 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2747 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2748 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2749 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2750 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2751 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2752 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2753 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2762 } toolbutton_info[NUM_TOOL_BUTTONS] =
2765 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2766 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2767 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2772 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2773 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2774 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2779 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2780 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2781 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2782 TOOL_CTRL_ID_CONFIRM,
2786 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2787 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2788 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2789 TOOL_CTRL_ID_PLAYER_1,
2793 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2794 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2795 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2796 TOOL_CTRL_ID_PLAYER_2,
2800 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2801 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2802 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2803 TOOL_CTRL_ID_PLAYER_3,
2807 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2808 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2809 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2810 TOOL_CTRL_ID_PLAYER_4,
2815 void CreateToolButtons()
2819 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2821 Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2822 Bitmap *deco_bitmap = None;
2823 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2824 struct GadgetInfo *gi;
2825 unsigned long event_mask;
2826 int gd_xoffset, gd_yoffset;
2827 int gd_x1, gd_x2, gd_y;
2830 event_mask = GD_EVENT_RELEASED;
2832 gd_xoffset = toolbutton_info[i].xpos;
2833 gd_yoffset = toolbutton_info[i].ypos;
2834 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2835 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2836 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2838 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2840 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
2842 getMiniGraphicSource(PLAYER_NR_GFX(IMG_PLAYER_1, player_nr),
2843 &deco_bitmap, &deco_x, &deco_y);
2844 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2845 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2848 gi = CreateGadget(GDI_CUSTOM_ID, id,
2849 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2850 GDI_X, DX + toolbutton_info[i].x,
2851 GDI_Y, DY + toolbutton_info[i].y,
2852 GDI_WIDTH, toolbutton_info[i].width,
2853 GDI_HEIGHT, toolbutton_info[i].height,
2854 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2855 GDI_STATE, GD_BUTTON_UNPRESSED,
2856 GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
2857 GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
2858 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
2859 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2860 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2861 GDI_DECORATION_SHIFTING, 1, 1,
2862 GDI_EVENT_MASK, event_mask,
2863 GDI_CALLBACK_ACTION, HandleToolButtons,
2867 Error(ERR_EXIT, "cannot create gadget");
2869 tool_gadget[id] = gi;
2873 void FreeToolButtons()
2877 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2878 FreeGadget(tool_gadget[i]);
2881 static void UnmapToolButtons()
2885 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2886 UnmapGadget(tool_gadget[i]);
2889 static void HandleToolButtons(struct GadgetInfo *gi)
2891 request_gadget_id = gi->custom_id;
2894 static struct Mapping_EM_to_RND_object
2897 boolean is_rnd_to_em_mapping; /* unique mapping EM <-> RND */
2898 boolean is_backside; /* backside of moving element */
2904 em_object_mapping_list[] =
2907 Xblank, TRUE, FALSE,
2911 Yacid_splash_eB, FALSE, FALSE,
2912 EL_ACID_SPLASH_RIGHT, -1, -1
2915 Yacid_splash_wB, FALSE, FALSE,
2916 EL_ACID_SPLASH_LEFT, -1, -1
2919 #ifdef EM_ENGINE_BAD_ROLL
2921 Xstone_force_e, FALSE, FALSE,
2922 EL_ROCK, -1, MV_BIT_RIGHT
2925 Xstone_force_w, FALSE, FALSE,
2926 EL_ROCK, -1, MV_BIT_LEFT
2929 Xnut_force_e, FALSE, FALSE,
2930 EL_NUT, -1, MV_BIT_RIGHT
2933 Xnut_force_w, FALSE, FALSE,
2934 EL_NUT, -1, MV_BIT_LEFT
2937 Xspring_force_e, FALSE, FALSE,
2938 EL_SPRING, -1, MV_BIT_RIGHT
2941 Xspring_force_w, FALSE, FALSE,
2942 EL_SPRING, -1, MV_BIT_LEFT
2945 Xemerald_force_e, FALSE, FALSE,
2946 EL_EMERALD, -1, MV_BIT_RIGHT
2949 Xemerald_force_w, FALSE, FALSE,
2950 EL_EMERALD, -1, MV_BIT_LEFT
2953 Xdiamond_force_e, FALSE, FALSE,
2954 EL_DIAMOND, -1, MV_BIT_RIGHT
2957 Xdiamond_force_w, FALSE, FALSE,
2958 EL_DIAMOND, -1, MV_BIT_LEFT
2961 Xbomb_force_e, FALSE, FALSE,
2962 EL_BOMB, -1, MV_BIT_RIGHT
2965 Xbomb_force_w, FALSE, FALSE,
2966 EL_BOMB, -1, MV_BIT_LEFT
2968 #endif /* EM_ENGINE_BAD_ROLL */
2971 Xstone, TRUE, FALSE,
2975 Xstone_pause, FALSE, FALSE,
2979 Xstone_fall, FALSE, FALSE,
2983 Ystone_s, FALSE, FALSE,
2984 EL_ROCK, ACTION_FALLING, -1
2987 Ystone_sB, FALSE, TRUE,
2988 EL_ROCK, ACTION_FALLING, -1
2991 Ystone_e, FALSE, FALSE,
2992 EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT
2995 Ystone_eB, FALSE, TRUE,
2996 EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT
2999 Ystone_w, FALSE, FALSE,
3000 EL_ROCK, ACTION_MOVING, MV_BIT_LEFT
3003 Ystone_wB, FALSE, TRUE,
3004 EL_ROCK, ACTION_MOVING, MV_BIT_LEFT
3011 Xnut_pause, FALSE, FALSE,
3015 Xnut_fall, FALSE, FALSE,
3019 Ynut_s, FALSE, FALSE,
3020 EL_NUT, ACTION_FALLING, -1
3023 Ynut_sB, FALSE, TRUE,
3024 EL_NUT, ACTION_FALLING, -1
3027 Ynut_e, FALSE, FALSE,
3028 EL_NUT, ACTION_MOVING, MV_BIT_RIGHT
3031 Ynut_eB, FALSE, TRUE,
3032 EL_NUT, ACTION_MOVING, MV_BIT_RIGHT
3035 Ynut_w, FALSE, FALSE,
3036 EL_NUT, ACTION_MOVING, MV_BIT_LEFT
3039 Ynut_wB, FALSE, TRUE,
3040 EL_NUT, ACTION_MOVING, MV_BIT_LEFT
3043 Xbug_n, TRUE, FALSE,
3047 Xbug_e, TRUE, FALSE,
3048 EL_BUG_RIGHT, -1, -1
3051 Xbug_s, TRUE, FALSE,
3055 Xbug_w, TRUE, FALSE,
3059 Xbug_gon, FALSE, FALSE,
3063 Xbug_goe, FALSE, FALSE,
3064 EL_BUG_RIGHT, -1, -1
3067 Xbug_gos, FALSE, FALSE,
3071 Xbug_gow, FALSE, FALSE,
3075 Ybug_n, FALSE, FALSE,
3076 EL_BUG, ACTION_MOVING, MV_BIT_UP
3079 Ybug_nB, FALSE, TRUE,
3080 EL_BUG, ACTION_MOVING, MV_BIT_UP
3083 Ybug_e, FALSE, FALSE,
3084 EL_BUG, ACTION_MOVING, MV_BIT_RIGHT
3087 Ybug_eB, FALSE, TRUE,
3088 EL_BUG, ACTION_MOVING, MV_BIT_RIGHT
3091 Ybug_s, FALSE, FALSE,
3092 EL_BUG, ACTION_MOVING, MV_BIT_DOWN
3095 Ybug_sB, FALSE, TRUE,
3096 EL_BUG, ACTION_MOVING, MV_BIT_DOWN
3099 Ybug_w, FALSE, FALSE,
3100 EL_BUG, ACTION_MOVING, MV_BIT_LEFT
3103 Ybug_wB, FALSE, TRUE,
3104 EL_BUG, ACTION_MOVING, MV_BIT_LEFT
3107 Ybug_w_n, FALSE, FALSE,
3108 EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_UP
3111 Ybug_n_e, FALSE, FALSE,
3112 EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3115 Ybug_e_s, FALSE, FALSE,
3116 EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
3119 Ybug_s_w, FALSE, FALSE,
3120 EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3123 Ybug_e_n, FALSE, FALSE,
3124 EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
3127 Ybug_s_e, FALSE, FALSE,
3128 EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3131 Ybug_w_s, FALSE, FALSE,
3132 EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
3135 Ybug_n_w, FALSE, FALSE,
3136 EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3139 Ybug_stone, FALSE, FALSE,
3140 EL_BUG, ACTION_SMASHED_BY_ROCK, -1
3143 Ybug_spring, FALSE, FALSE,
3144 EL_BUG, ACTION_SMASHED_BY_SPRING, -1
3147 Xtank_n, TRUE, FALSE,
3148 EL_SPACESHIP_UP, -1, -1
3151 Xtank_e, TRUE, FALSE,
3152 EL_SPACESHIP_RIGHT, -1, -1
3155 Xtank_s, TRUE, FALSE,
3156 EL_SPACESHIP_DOWN, -1, -1
3159 Xtank_w, TRUE, FALSE,
3160 EL_SPACESHIP_LEFT, -1, -1
3163 Xtank_gon, FALSE, FALSE,
3164 EL_SPACESHIP_UP, -1, -1
3167 Xtank_goe, FALSE, FALSE,
3168 EL_SPACESHIP_RIGHT, -1, -1
3171 Xtank_gos, FALSE, FALSE,
3172 EL_SPACESHIP_DOWN, -1, -1
3175 Xtank_gow, FALSE, FALSE,
3176 EL_SPACESHIP_LEFT, -1, -1
3179 Ytank_n, FALSE, FALSE,
3180 EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP
3183 Ytank_nB, FALSE, TRUE,
3184 EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP
3187 Ytank_e, FALSE, FALSE,
3188 EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT
3191 Ytank_eB, FALSE, TRUE,
3192 EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT
3195 Ytank_s, FALSE, FALSE,
3196 EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN
3199 Ytank_sB, FALSE, TRUE,
3200 EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN
3203 Ytank_w, FALSE, FALSE,
3204 EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT
3207 Ytank_wB, FALSE, TRUE,
3208 EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT
3211 Ytank_w_n, FALSE, FALSE,
3212 EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_UP
3215 Ytank_n_e, FALSE, FALSE,
3216 EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3219 Ytank_e_s, FALSE, FALSE,
3220 EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
3223 Ytank_s_w, FALSE, FALSE,
3224 EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3227 Ytank_e_n, FALSE, FALSE,
3228 EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
3231 Ytank_s_e, FALSE, FALSE,
3232 EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3235 Ytank_w_s, FALSE, FALSE,
3236 EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
3239 Ytank_n_w, FALSE, FALSE,
3240 EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3243 Ytank_stone, FALSE, FALSE,
3244 EL_SPACESHIP, ACTION_SMASHED_BY_ROCK, -1
3247 Ytank_spring, FALSE, FALSE,
3248 EL_SPACESHIP, ACTION_SMASHED_BY_SPRING, -1
3251 Xandroid, TRUE, FALSE,
3252 EL_EMC_ANDROID, ACTION_ACTIVE, -1
3255 Xandroid_1_n, FALSE, FALSE,
3256 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_UP
3259 Xandroid_2_n, FALSE, FALSE,
3260 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_UP
3263 Xandroid_1_e, FALSE, FALSE,
3264 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_RIGHT
3267 Xandroid_2_e, FALSE, FALSE,
3268 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_RIGHT
3271 Xandroid_1_w, FALSE, FALSE,
3272 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_LEFT
3275 Xandroid_2_w, FALSE, FALSE,
3276 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_LEFT
3279 Xandroid_1_s, FALSE, FALSE,
3280 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_DOWN
3283 Xandroid_2_s, FALSE, FALSE,
3284 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_DOWN
3287 Yandroid_n, FALSE, FALSE,
3288 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_UP
3291 Yandroid_nB, FALSE, TRUE,
3292 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_UP
3295 Yandroid_ne, FALSE, FALSE,
3296 EL_EMC_ANDROID, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3299 Yandroid_neB, FALSE, TRUE,
3300 EL_EMC_ANDROID, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3303 Yandroid_e, FALSE, FALSE,
3304 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_RIGHT
3307 Yandroid_eB, FALSE, TRUE,
3308 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_RIGHT
3311 Yandroid_se, FALSE, FALSE,
3312 EL_EMC_ANDROID, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3315 Yandroid_seB, FALSE, TRUE,
3316 EL_EMC_ANDROID, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3319 Yandroid_s, FALSE, FALSE,
3320 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_DOWN
3323 Yandroid_sB, FALSE, TRUE,
3324 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_DOWN
3327 Yandroid_sw, FALSE, FALSE,
3328 EL_EMC_ANDROID, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3331 Yandroid_swB, FALSE, TRUE,
3332 EL_EMC_ANDROID, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3335 Yandroid_w, FALSE, FALSE,
3336 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_LEFT
3339 Yandroid_wB, FALSE, TRUE,
3340 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_LEFT
3343 Yandroid_nw, FALSE, FALSE,
3344 EL_EMC_ANDROID, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3347 Yandroid_nwB, FALSE, TRUE,
3348 EL_EMC_ANDROID, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3351 Xspring, TRUE, FALSE,
3355 Xspring_pause, FALSE, FALSE,
3359 Xspring_e, FALSE, FALSE,
3363 Xspring_w, FALSE, FALSE,
3367 Xspring_fall, FALSE, FALSE,
3371 Yspring_s, FALSE, FALSE,
3372 EL_SPRING, ACTION_FALLING, -1
3375 Yspring_sB, FALSE, TRUE,
3376 EL_SPRING, ACTION_FALLING, -1
3379 Yspring_e, FALSE, FALSE,
3380 EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT
3383 Yspring_eB, FALSE, TRUE,
3384 EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT
3387 Yspring_w, FALSE, FALSE,
3388 EL_SPRING, ACTION_MOVING, MV_BIT_LEFT
3391 Yspring_wB, FALSE, TRUE,
3392 EL_SPRING, ACTION_MOVING, MV_BIT_LEFT
3395 Yspring_kill_e, FALSE, FALSE,
3396 EL_ROBOT, ACTION_SLURPED_BY_SPRING, MV_BIT_RIGHT
3399 Yspring_kill_eB, FALSE, TRUE,
3400 EL_ROBOT, ACTION_SLURPED_BY_SPRING, MV_BIT_RIGHT
3403 Yspring_kill_w, FALSE, FALSE,
3404 EL_ROBOT, ACTION_SLURPED_BY_SPRING, MV_BIT_LEFT
3407 Yspring_kill_wB, FALSE, TRUE,
3408 EL_ROBOT, ACTION_SLURPED_BY_SPRING, MV_BIT_LEFT
3411 Xeater_n, TRUE, FALSE,
3415 Xeater_e, FALSE, FALSE,
3419 Xeater_w, FALSE, FALSE,
3423 Xeater_s, FALSE, FALSE,
3427 Yeater_n, FALSE, FALSE,
3428 EL_YAMYAM, ACTION_MOVING, MV_BIT_UP
3431 Yeater_nB, FALSE, TRUE,
3432 EL_YAMYAM, ACTION_MOVING, MV_BIT_UP
3435 Yeater_e, FALSE, FALSE,
3436 EL_YAMYAM, ACTION_MOVING, MV_BIT_RIGHT
3439 Yeater_eB, FALSE, TRUE,
3440 EL_YAMYAM, ACTION_MOVING, MV_BIT_RIGHT
3443 Yeater_s, FALSE, FALSE,
3444 EL_YAMYAM, ACTION_MOVING, MV_BIT_DOWN
3447 Yeater_sB, FALSE, TRUE,
3448 EL_YAMYAM, ACTION_MOVING, MV_BIT_DOWN
3451 Yeater_w, FALSE, FALSE,
3452 EL_YAMYAM, ACTION_MOVING, MV_BIT_LEFT
3455 Yeater_wB, FALSE, TRUE,
3456 EL_YAMYAM, ACTION_MOVING, MV_BIT_LEFT
3459 Yeater_stone, FALSE, FALSE,
3460 EL_YAMYAM, ACTION_SMASHED_BY_ROCK, -1
3463 Yeater_spring, FALSE, FALSE,
3464 EL_YAMYAM, ACTION_SMASHED_BY_SPRING, -1
3467 Xalien, TRUE, FALSE,
3471 Xalien_pause, FALSE, FALSE,
3475 Yalien_n, FALSE, FALSE,
3476 EL_ROBOT, ACTION_MOVING, MV_BIT_UP
3479 Yalien_nB, FALSE, TRUE,
3480 EL_ROBOT, ACTION_MOVING, MV_BIT_UP
3483 Yalien_e, FALSE, FALSE,
3484 EL_ROBOT, ACTION_MOVING, MV_BIT_RIGHT
3487 Yalien_eB, FALSE, TRUE,
3488 EL_ROBOT, ACTION_MOVING, MV_BIT_RIGHT
3491 Yalien_s, FALSE, FALSE,
3492 EL_ROBOT, ACTION_MOVING, MV_BIT_DOWN
3495 Yalien_sB, FALSE, TRUE,
3496 EL_ROBOT, ACTION_MOVING, MV_BIT_DOWN
3499 Yalien_w, FALSE, FALSE,
3500 EL_ROBOT, ACTION_MOVING, MV_BIT_LEFT
3503 Yalien_wB, FALSE, TRUE,
3504 EL_ROBOT, ACTION_MOVING, MV_BIT_LEFT
3507 Yalien_stone, FALSE, FALSE,
3508 EL_ROBOT, ACTION_SMASHED_BY_ROCK, -1
3511 Yalien_spring, FALSE, FALSE,
3512 EL_ROBOT, ACTION_SMASHED_BY_SPRING, -1
3515 Xemerald, TRUE, FALSE,
3519 Xemerald_pause, FALSE, FALSE,
3523 Xemerald_fall, FALSE, FALSE,
3527 Xemerald_shine, FALSE, FALSE,
3528 EL_EMERALD, ACTION_TWINKLING, -1
3531 Yemerald_s, FALSE, FALSE,
3532 EL_EMERALD, ACTION_FALLING, -1
3535 Yemerald_sB, FALSE, TRUE,
3536 EL_EMERALD, ACTION_FALLING, -1
3539 Yemerald_e, FALSE, FALSE,
3540 EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT
3543 Yemerald_eB, FALSE, TRUE,
3544 EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT
3547 Yemerald_w, FALSE, FALSE,
3548 EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT
3551 Yemerald_wB, FALSE, TRUE,
3552 EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT
3555 Yemerald_eat, FALSE, FALSE,
3556 EL_EMERALD, ACTION_COLLECTING, -1
3559 Yemerald_stone, FALSE, FALSE,
3560 EL_NUT, ACTION_BREAKING, -1
3563 Xdiamond, TRUE, FALSE,
3567 Xdiamond_pause, FALSE, FALSE,
3571 Xdiamond_fall, FALSE, FALSE,
3575 Xdiamond_shine, FALSE, FALSE,
3576 EL_DIAMOND, ACTION_TWINKLING, -1
3579 Ydiamond_s, FALSE, FALSE,
3580 EL_DIAMOND, ACTION_FALLING, -1
3583 Ydiamond_sB, FALSE, TRUE,
3584 EL_DIAMOND, ACTION_FALLING, -1
3587 Ydiamond_e, FALSE, FALSE,
3588 EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT
3591 Ydiamond_eB, FALSE, TRUE,
3592 EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT
3595 Ydiamond_w, FALSE, FALSE,
3596 EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT
3599 Ydiamond_wB, FALSE, TRUE,
3600 EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT
3603 Ydiamond_eat, FALSE, FALSE,
3604 EL_DIAMOND, ACTION_COLLECTING, -1
3607 Ydiamond_stone, FALSE, FALSE,
3608 EL_DIAMOND, ACTION_SMASHED_BY_ROCK, -1
3611 Xdrip_fall, TRUE, FALSE,
3612 EL_AMOEBA_DROP, -1, -1
3615 Xdrip_stretch, FALSE, FALSE,
3616 EL_AMOEBA_DROP, ACTION_FALLING, -1
3619 Xdrip_stretchB, FALSE, TRUE,
3620 EL_AMOEBA_DROP, ACTION_FALLING, -1
3623 Xdrip_eat, FALSE, FALSE,
3624 EL_AMOEBA_DROP, ACTION_GROWING, -1
3627 Ydrip_s1, FALSE, FALSE,
3628 EL_AMOEBA_DROP, ACTION_FALLING, -1
3631 Ydrip_s1B, FALSE, TRUE,
3632 EL_AMOEBA_DROP, ACTION_FALLING, -1
3635 Ydrip_s2, FALSE, FALSE,
3636 EL_AMOEBA_DROP, ACTION_FALLING, -1
3639 Ydrip_s2B, FALSE, TRUE,
3640 EL_AMOEBA_DROP, ACTION_FALLING, -1
3647 Xbomb_pause, FALSE, FALSE,
3651 Xbomb_fall, FALSE, FALSE,
3655 Ybomb_s, FALSE, FALSE,
3656 EL_BOMB, ACTION_FALLING, -1
3659 Ybomb_sB, FALSE, TRUE,
3660 EL_BOMB, ACTION_FALLING, -1
3663 Ybomb_e, FALSE, FALSE,
3664 EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT
3667 Ybomb_eB, FALSE, TRUE,
3668 EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT
3671 Ybomb_w, FALSE, FALSE,
3672 EL_BOMB, ACTION_MOVING, MV_BIT_LEFT
3675 Ybomb_wB, FALSE, TRUE,
3676 EL_BOMB, ACTION_MOVING, MV_BIT_LEFT
3679 Ybomb_eat, FALSE, FALSE,
3680 EL_BOMB, ACTION_ACTIVATING, -1
3683 Xballoon, TRUE, FALSE,
3687 Yballoon_n, FALSE, FALSE,
3688 EL_BALLOON, ACTION_MOVING, MV_BIT_UP
3691 Yballoon_nB, FALSE, TRUE,
3692 EL_BALLOON, ACTION_MOVING, MV_BIT_UP
3695 Yballoon_e, FALSE, FALSE,
3696 EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT
3699 Yballoon_eB, FALSE, TRUE,
3700 EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT
3703 Yballoon_s, FALSE, FALSE,
3704 EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN
3707 Yballoon_sB, FALSE, TRUE,
3708 EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN
3711 Yballoon_w, FALSE, FALSE,
3712 EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT
3715 Yballoon_wB, FALSE, TRUE,
3716 EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT
3719 Xgrass, TRUE, FALSE,
3720 EL_EMC_GRASS, -1, -1
3723 Ygrass_nB, FALSE, FALSE,
3724 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_UP
3727 Ygrass_eB, FALSE, FALSE,
3728 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_RIGHT
3731 Ygrass_sB, FALSE, FALSE,
3732 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_DOWN
3735 Ygrass_wB, FALSE, FALSE,
3736 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_LEFT
3743 Ydirt_nB, FALSE, FALSE,
3744 EL_SAND, ACTION_DIGGING, MV_BIT_UP
3747 Ydirt_eB, FALSE, FALSE,
3748 EL_SAND, ACTION_DIGGING, MV_BIT_RIGHT
3751 Ydirt_sB, FALSE, FALSE,
3752 EL_SAND, ACTION_DIGGING, MV_BIT_DOWN
3755 Ydirt_wB, FALSE, FALSE,
3756 EL_SAND, ACTION_DIGGING, MV_BIT_LEFT
3759 Xacid_ne, TRUE, FALSE,
3760 EL_ACID_POOL_TOPRIGHT, -1, -1
3763 Xacid_se, TRUE, FALSE,
3764 EL_ACID_POOL_BOTTOMRIGHT, -1, -1
3767 Xacid_s, TRUE, FALSE,
3768 EL_ACID_POOL_BOTTOM, -1, -1
3771 Xacid_sw, TRUE, FALSE,
3772 EL_ACID_POOL_BOTTOMLEFT, -1, -1
3775 Xacid_nw, TRUE, FALSE,
3776 EL_ACID_POOL_TOPLEFT, -1, -1
3779 Xacid_1, TRUE, FALSE,
3783 Xacid_2, FALSE, FALSE,
3787 Xacid_3, FALSE, FALSE,
3791 Xacid_4, FALSE, FALSE,
3795 Xacid_5, FALSE, FALSE,
3799 Xacid_6, FALSE, FALSE,
3803 Xacid_7, FALSE, FALSE,
3807 Xacid_8, FALSE, FALSE,
3811 Xball_1, TRUE, FALSE,
3812 EL_EMC_MAGIC_BALL, -1, -1
3815 Xball_1B, FALSE, FALSE,
3816 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
3819 Xball_2, FALSE, FALSE,
3820 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
3823 Xball_2B, FALSE, FALSE,
3824 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
3827 Yball_eat, FALSE, FALSE,
3828 EL_EMC_MAGIC_BALL, ACTION_DROPPING, -1
3831 Ykey_1_eat, FALSE, FALSE,
3832 EL_EM_KEY_1, ACTION_COLLECTING, -1
3835 Ykey_2_eat, FALSE, FALSE,
3836 EL_EM_KEY_2, ACTION_COLLECTING, -1
3839 Ykey_3_eat, FALSE, FALSE,
3840 EL_EM_KEY_3, ACTION_COLLECTING, -1
3843 Ykey_4_eat, FALSE, FALSE,
3844 EL_EM_KEY_4, ACTION_COLLECTING, -1
3847 Ykey_5_eat, FALSE, FALSE,
3848 EL_EMC_KEY_5, ACTION_COLLECTING, -1
3851 Ykey_6_eat, FALSE, FALSE,
3852 EL_EMC_KEY_6, ACTION_COLLECTING, -1
3855 Ykey_7_eat, FALSE, FALSE,
3856 EL_EMC_KEY_7, ACTION_COLLECTING, -1
3859 Ykey_8_eat, FALSE, FALSE,
3860 EL_EMC_KEY_8, ACTION_COLLECTING, -1
3863 Ylenses_eat, FALSE, FALSE,
3864 EL_EMC_LENSES, ACTION_COLLECTING, -1
3867 Ymagnify_eat, FALSE, FALSE,
3868 EL_EMC_MAGNIFIER, ACTION_COLLECTING, -1
3871 Ygrass_eat, FALSE, FALSE,
3872 EL_EMC_GRASS, ACTION_SNAPPING, -1
3875 Ydirt_eat, FALSE, FALSE,
3876 EL_SAND, ACTION_SNAPPING, -1
3879 Xgrow_ns, TRUE, FALSE,
3880 EL_EXPANDABLE_WALL_VERTICAL, -1, -1
3883 Ygrow_ns_eat, FALSE, FALSE,
3884 EL_EXPANDABLE_WALL_VERTICAL, ACTION_GROWING, -1
3887 Xgrow_ew, TRUE, FALSE,
3888 EL_EXPANDABLE_WALL_HORIZONTAL, -1, -1
3891 Ygrow_ew_eat, FALSE, FALSE,
3892 EL_EXPANDABLE_WALL_HORIZONTAL, ACTION_GROWING, -1
3895 Xwonderwall, TRUE, FALSE,
3896 EL_MAGIC_WALL, -1, -1
3899 XwonderwallB, FALSE, FALSE,
3900 EL_MAGIC_WALL, ACTION_ACTIVE, -1
3903 Xamoeba_1, TRUE, FALSE,
3904 EL_AMOEBA_DRY, ACTION_OTHER, -1
3907 Xamoeba_2, FALSE, FALSE,
3908 EL_AMOEBA_DRY, ACTION_OTHER, -1
3911 Xamoeba_3, FALSE, FALSE,
3912 EL_AMOEBA_DRY, ACTION_OTHER, -1
3915 Xamoeba_4, FALSE, FALSE,
3916 EL_AMOEBA_DRY, ACTION_OTHER, -1
3919 Xamoeba_5, TRUE, FALSE,
3920 EL_AMOEBA_WET, ACTION_OTHER, -1
3923 Xamoeba_6, FALSE, FALSE,
3924 EL_AMOEBA_WET, ACTION_OTHER, -1
3927 Xamoeba_7, FALSE, FALSE,
3928 EL_AMOEBA_WET, ACTION_OTHER, -1
3931 Xamoeba_8, FALSE, FALSE,
3932 EL_AMOEBA_WET, ACTION_OTHER, -1
3935 Xdoor_1, TRUE, FALSE,
3936 EL_EM_GATE_1, -1, -1
3939 Xdoor_2, TRUE, FALSE,
3940 EL_EM_GATE_2, -1, -1
3943 Xdoor_3, TRUE, FALSE,
3944 EL_EM_GATE_3, -1, -1
3947 Xdoor_4, TRUE, FALSE,
3948 EL_EM_GATE_4, -1, -1
3951 Xdoor_5, TRUE, FALSE,
3952 EL_EMC_GATE_5, -1, -1
3955 Xdoor_6, TRUE, FALSE,
3956 EL_EMC_GATE_6, -1, -1
3959 Xdoor_7, TRUE, FALSE,
3960 EL_EMC_GATE_7, -1, -1
3963 Xdoor_8, TRUE, FALSE,
3964 EL_EMC_GATE_8, -1, -1
3967 Xkey_1, TRUE, FALSE,
3971 Xkey_2, TRUE, FALSE,
3975 Xkey_3, TRUE, FALSE,
3979 Xkey_4, TRUE, FALSE,
3983 Xkey_5, TRUE, FALSE,
3984 EL_EMC_KEY_5, -1, -1
3987 Xkey_6, TRUE, FALSE,
3988 EL_EMC_KEY_6, -1, -1
3991 Xkey_7, TRUE, FALSE,
3992 EL_EMC_KEY_7, -1, -1
3995 Xkey_8, TRUE, FALSE,
3996 EL_EMC_KEY_8, -1, -1
3999 Xwind_n, TRUE, FALSE,
4000 EL_BALLOON_SWITCH_UP, -1, -1
4003 Xwind_e, TRUE, FALSE,
4004 EL_BALLOON_SWITCH_RIGHT, -1, -1
4007 Xwind_s, TRUE, FALSE,
4008 EL_BALLOON_SWITCH_DOWN, -1, -1
4011 Xwind_w, TRUE, FALSE,
4012 EL_BALLOON_SWITCH_LEFT, -1, -1
4015 Xwind_nesw, TRUE, FALSE,
4016 EL_BALLOON_SWITCH_ANY, -1, -1
4019 Xwind_stop, TRUE, FALSE,
4020 EL_BALLOON_SWITCH_NONE, -1, -1
4024 EL_EXIT_CLOSED, -1, -1
4027 Xexit_1, TRUE, FALSE,
4028 EL_EXIT_OPEN, -1, -1
4031 Xexit_2, FALSE, FALSE,
4032 EL_EXIT_OPEN, -1, -1
4035 Xexit_3, FALSE, FALSE,
4036 EL_EXIT_OPEN, -1, -1
4039 Xdynamite, TRUE, FALSE,
4043 Ydynamite_eat, FALSE, FALSE,
4044 EL_DYNAMITE, ACTION_COLLECTING, -1
4047 Xdynamite_1, TRUE, FALSE,
4048 EL_DYNAMITE_ACTIVE, -1, -1
4051 Xdynamite_2, FALSE, FALSE,
4052 EL_DYNAMITE_ACTIVE, -1, -1
4055 Xdynamite_3, FALSE, FALSE,
4056 EL_DYNAMITE_ACTIVE, -1, -1
4059 Xdynamite_4, FALSE, FALSE,
4060 EL_DYNAMITE_ACTIVE, -1, -1
4063 Xbumper, TRUE, FALSE,
4064 EL_EMC_SPRING_BUMPER, -1, -1
4067 XbumperB, FALSE, FALSE,
4068 EL_EMC_SPRING_BUMPER, ACTION_ACTIVE, -1
4071 Xwheel, TRUE, FALSE,
4072 EL_ROBOT_WHEEL, -1, -1
4075 XwheelB, FALSE, FALSE,
4076 EL_ROBOT_WHEEL, ACTION_ACTIVE, -1
4079 Xswitch, TRUE, FALSE,
4080 EL_EMC_MAGIC_BALL_SWITCH, -1, -1
4083 XswitchB, FALSE, FALSE,
4084 EL_EMC_MAGIC_BALL_SWITCH, ACTION_ACTIVE, -1
4088 EL_QUICKSAND_EMPTY, -1, -1
4091 Xsand_stone, TRUE, FALSE,
4092 EL_QUICKSAND_FULL, -1, -1
4095 Xsand_stonein_1, FALSE, FALSE,
4096 EL_ROCK, ACTION_FILLING, -1
4099 Xsand_stonein_2, FALSE, FALSE,
4100 EL_ROCK, ACTION_FILLING, -1
4103 Xsand_stonein_3, FALSE, FALSE,
4104 EL_ROCK, ACTION_FILLING, -1
4107 Xsand_stonein_4, FALSE, FALSE,
4108 EL_ROCK, ACTION_FILLING, -1
4111 Xsand_stonesand_1, FALSE, FALSE,
4112 EL_QUICKSAND_FULL, -1, -1
4115 Xsand_stonesand_2, FALSE, FALSE,
4116 EL_QUICKSAND_FULL, -1, -1
4119 Xsand_stonesand_3, FALSE, FALSE,
4120 EL_QUICKSAND_FULL, -1, -1
4123 Xsand_stonesand_4, FALSE, FALSE,
4124 EL_QUICKSAND_FULL, -1, -1
4127 Xsand_stoneout_1, FALSE, FALSE,
4128 EL_ROCK, ACTION_EMPTYING, -1
4131 Xsand_stoneout_2, FALSE, FALSE,
4132 EL_ROCK, ACTION_EMPTYING, -1
4135 Xsand_sandstone_1, FALSE, FALSE,
4136 EL_QUICKSAND_FULL, -1, -1
4139 Xsand_sandstone_2, FALSE, FALSE,
4140 EL_QUICKSAND_FULL, -1, -1
4143 Xsand_sandstone_3, FALSE, FALSE,
4144 EL_QUICKSAND_FULL, -1, -1
4147 Xsand_sandstone_4, FALSE, FALSE,
4148 EL_QUICKSAND_FULL, -1, -1
4151 Xplant, TRUE, FALSE,
4152 EL_EMC_PLANT, -1, -1
4155 Yplant, FALSE, FALSE,
4156 EL_EMC_PLANT, -1, -1
4159 Xlenses, TRUE, FALSE,
4160 EL_EMC_LENSES, -1, -1
4163 Xmagnify, TRUE, FALSE,
4164 EL_EMC_MAGNIFIER, -1, -1
4167 Xdripper, TRUE, FALSE,
4168 EL_EMC_DRIPPER, -1, -1
4171 XdripperB, FALSE, FALSE,
4172 EL_EMC_DRIPPER, ACTION_ACTIVE, -1
4175 Xfake_blank, TRUE, FALSE,
4176 EL_INVISIBLE_WALL, -1, -1
4179 Xfake_blankB, FALSE, FALSE,
4180 EL_INVISIBLE_WALL, ACTION_ACTIVE, -1
4183 Xfake_grass, TRUE, FALSE,
4184 EL_EMC_FAKE_GRASS, -1, -1
4187 Xfake_grassB, FALSE, FALSE,
4188 EL_EMC_FAKE_GRASS, ACTION_ACTIVE, -1
4191 Xfake_door_1, TRUE, FALSE,
4192 EL_EM_GATE_1_GRAY, -1, -1
4195 Xfake_door_2, TRUE, FALSE,
4196 EL_EM_GATE_2_GRAY, -1, -1
4199 Xfake_door_3, TRUE, FALSE,
4200 EL_EM_GATE_3_GRAY, -1, -1
4203 Xfake_door_4, TRUE, FALSE,
4204 EL_EM_GATE_4_GRAY, -1, -1
4207 Xfake_door_5, TRUE, FALSE,
4208 EL_EMC_GATE_5_GRAY, -1, -1
4211 Xfake_door_6, TRUE, FALSE,
4212 EL_EMC_GATE_6_GRAY, -1, -1
4215 Xfake_door_7, TRUE, FALSE,
4216 EL_EMC_GATE_7_GRAY, -1, -1
4219 Xfake_door_8, TRUE, FALSE,
4220 EL_EMC_GATE_8_GRAY, -1, -1
4223 Xfake_acid_1, TRUE, FALSE,
4224 EL_EMC_FAKE_ACID, -1, -1
4227 Xfake_acid_2, FALSE, FALSE,
4228 EL_EMC_FAKE_ACID, -1, -1
4231 Xfake_acid_3, FALSE, FALSE,
4232 EL_EMC_FAKE_ACID, -1, -1
4235 Xfake_acid_4, FALSE, FALSE,
4236 EL_EMC_FAKE_ACID, -1, -1
4239 Xfake_acid_5, FALSE, FALSE,
4240 EL_EMC_FAKE_ACID, -1, -1
4243 Xfake_acid_6, FALSE, FALSE,
4244 EL_EMC_FAKE_ACID, -1, -1
4247 Xfake_acid_7, FALSE, FALSE,
4248 EL_EMC_FAKE_ACID, -1, -1
4251 Xfake_acid_8, FALSE, FALSE,
4252 EL_EMC_FAKE_ACID, -1, -1
4255 Xsteel_1, TRUE, FALSE,
4256 EL_STEELWALL, -1, -1
4259 Xsteel_2, TRUE, FALSE,
4260 EL_EMC_STEELWALL_2, -1, -1
4263 Xsteel_3, TRUE, FALSE,
4264 EL_EMC_STEELWALL_3, -1, -1
4267 Xsteel_4, TRUE, FALSE,
4268 EL_EMC_STEELWALL_4, -1, -1
4271 Xwall_1, TRUE, FALSE,
4275 Xwall_2, TRUE, FALSE,
4276 EL_EMC_WALL_14, -1, -1
4279 Xwall_3, TRUE, FALSE,
4280 EL_EMC_WALL_15, -1, -1
4283 Xwall_4, TRUE, FALSE,
4284 EL_EMC_WALL_16, -1, -1
4287 Xround_wall_1, TRUE, FALSE,
4288 EL_WALL_SLIPPERY, -1, -1
4291 Xround_wall_2, TRUE, FALSE,
4292 EL_EMC_WALL_SLIPPERY_2, -1, -1
4295 Xround_wall_3, TRUE, FALSE,
4296 EL_EMC_WALL_SLIPPERY_3, -1, -1
4299 Xround_wall_4, TRUE, FALSE,
4300 EL_EMC_WALL_SLIPPERY_4, -1, -1
4303 Xdecor_1, TRUE, FALSE,
4304 EL_EMC_WALL_8, -1, -1
4307 Xdecor_2, TRUE, FALSE,
4308 EL_EMC_WALL_6, -1, -1
4311 Xdecor_3, TRUE, FALSE,
4312 EL_EMC_WALL_4, -1, -1
4315 Xdecor_4, TRUE, FALSE,
4316 EL_EMC_WALL_7, -1, -1
4319 Xdecor_5, TRUE, FALSE,
4320 EL_EMC_WALL_5, -1, -1
4323 Xdecor_6, TRUE, FALSE,
4324 EL_EMC_WALL_9, -1, -1
4327 Xdecor_7, TRUE, FALSE,
4328 EL_EMC_WALL_10, -1, -1
4331 Xdecor_8, TRUE, FALSE,
4332 EL_EMC_WALL_1, -1, -1
4335 Xdecor_9, TRUE, FALSE,
4336 EL_EMC_WALL_2, -1, -1
4339 Xdecor_10, TRUE, FALSE,
4340 EL_EMC_WALL_3, -1, -1
4343 Xdecor_11, TRUE, FALSE,
4344 EL_EMC_WALL_11, -1, -1
4347 Xdecor_12, TRUE, FALSE,
4348 EL_EMC_WALL_12, -1, -1
4351 Xalpha_0, TRUE, FALSE,
4352 EL_CHAR('0'), -1, -1
4355 Xalpha_1, TRUE, FALSE,
4356 EL_CHAR('1'), -1, -1
4359 Xalpha_2, TRUE, FALSE,
4360 EL_CHAR('2'), -1, -1
4363 Xalpha_3, TRUE, FALSE,
4364 EL_CHAR('3'), -1, -1
4367 Xalpha_4, TRUE, FALSE,
4368 EL_CHAR('4'), -1, -1
4371 Xalpha_5, TRUE, FALSE,
4372 EL_CHAR('5'), -1, -1
4375 Xalpha_6, TRUE, FALSE,
4376 EL_CHAR('6'), -1, -1
4379 Xalpha_7, TRUE, FALSE,
4380 EL_CHAR('7'), -1, -1
4383 Xalpha_8, TRUE, FALSE,
4384 EL_CHAR('8'), -1, -1
4387 Xalpha_9, TRUE, FALSE,
4388 EL_CHAR('9'), -1, -1
4391 Xalpha_excla, TRUE, FALSE,
4392 EL_CHAR('!'), -1, -1
4395 Xalpha_quote, TRUE, FALSE,
4396 EL_CHAR('"'), -1, -1
4399 Xalpha_comma, TRUE, FALSE,
4400 EL_CHAR(','), -1, -1
4403 Xalpha_minus, TRUE, FALSE,
4404 EL_CHAR('-'), -1, -1
4407 Xalpha_perio, TRUE, FALSE,
4408 EL_CHAR('.'), -1, -1
4411 Xalpha_colon, TRUE, FALSE,
4412 EL_CHAR(':'), -1, -1
4415 Xalpha_quest, TRUE, FALSE,
4416 EL_CHAR('?'), -1, -1
4419 Xalpha_a, TRUE, FALSE,
4420 EL_CHAR('A'), -1, -1
4423 Xalpha_b, TRUE, FALSE,
4424 EL_CHAR('B'), -1, -1
4427 Xalpha_c, TRUE, FALSE,
4428 EL_CHAR('C'), -1, -1
4431 Xalpha_d, TRUE, FALSE,
4432 EL_CHAR('D'), -1, -1
4435 Xalpha_e, TRUE, FALSE,
4436 EL_CHAR('E'), -1, -1
4439 Xalpha_f, TRUE, FALSE,
4440 EL_CHAR('F'), -1, -1
4443 Xalpha_g, TRUE, FALSE,
4444 EL_CHAR('G'), -1, -1
4447 Xalpha_h, TRUE, FALSE,
4448 EL_CHAR('H'), -1, -1
4451 Xalpha_i, TRUE, FALSE,
4452 EL_CHAR('I'), -1, -1
4455 Xalpha_j, TRUE, FALSE,
4456 EL_CHAR('J'), -1, -1
4459 Xalpha_k, TRUE, FALSE,
4460 EL_CHAR('K'), -1, -1
4463 Xalpha_l, TRUE, FALSE,
4464 EL_CHAR('L'), -1, -1
4467 Xalpha_m, TRUE, FALSE,
4468 EL_CHAR('M'), -1, -1
4471 Xalpha_n, TRUE, FALSE,
4472 EL_CHAR('N'), -1, -1
4475 Xalpha_o, TRUE, FALSE,
4476 EL_CHAR('O'), -1, -1
4479 Xalpha_p, TRUE, FALSE,
4480 EL_CHAR('P'), -1, -1
4483 Xalpha_q, TRUE, FALSE,
4484 EL_CHAR('Q'), -1, -1
4487 Xalpha_r, TRUE, FALSE,
4488 EL_CHAR('R'), -1, -1
4491 Xalpha_s, TRUE, FALSE,
4492 EL_CHAR('S'), -1, -1
4495 Xalpha_t, TRUE, FALSE,
4496 EL_CHAR('T'), -1, -1
4499 Xalpha_u, TRUE, FALSE,
4500 EL_CHAR('U'), -1, -1
4503 Xalpha_v, TRUE, FALSE,
4504 EL_CHAR('V'), -1, -1
4507 Xalpha_w, TRUE, FALSE,
4508 EL_CHAR('W'), -1, -1
4511 Xalpha_x, TRUE, FALSE,
4512 EL_CHAR('X'), -1, -1
4515 Xalpha_y, TRUE, FALSE,
4516 EL_CHAR('Y'), -1, -1
4519 Xalpha_z, TRUE, FALSE,
4520 EL_CHAR('Z'), -1, -1
4523 Xalpha_arrow_e, TRUE, FALSE,
4524 EL_CHAR('>'), -1, -1
4527 Xalpha_arrow_w, TRUE, FALSE,
4528 EL_CHAR('<'), -1, -1
4531 Xalpha_copyr, TRUE, FALSE,
4532 EL_CHAR('©'), -1, -1
4535 Xalpha_copyr, TRUE, FALSE,
4536 EL_CHAR('©'), -1, -1
4540 Xboom_bug, FALSE, FALSE,
4541 EL_BUG, ACTION_EXPLODING, -1
4544 Xboom_bomb, FALSE, FALSE,
4545 EL_BOMB, ACTION_EXPLODING, -1
4548 Xboom_android, FALSE, FALSE,
4549 EL_EMC_ANDROID, ACTION_OTHER, -1
4552 Xboom_1, FALSE, FALSE,
4553 EL_DEFAULT, ACTION_EXPLODING, -1
4556 Xboom_2, FALSE, FALSE,
4557 EL_DEFAULT, ACTION_EXPLODING, -1
4560 Znormal, FALSE, FALSE,
4564 Zdynamite, FALSE, FALSE,
4568 Zplayer, FALSE, FALSE,
4572 ZBORDER, FALSE, FALSE,
4582 static struct Mapping_EM_to_RND_player
4591 em_player_mapping_list[] =
4595 EL_PLAYER_1, ACTION_MOVING, MV_BIT_UP,
4599 EL_PLAYER_1, ACTION_MOVING, MV_BIT_RIGHT,
4603 EL_PLAYER_1, ACTION_MOVING, MV_BIT_DOWN,
4607 EL_PLAYER_1, ACTION_MOVING, MV_BIT_LEFT,
4611 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_UP,
4615 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_RIGHT,
4619 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_DOWN,
4623 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_LEFT,
4627 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_UP,
4631 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_RIGHT,
4635 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_DOWN,
4639 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_LEFT,
4643 EL_PLAYER_2, ACTION_MOVING, MV_BIT_UP,
4647 EL_PLAYER_2, ACTION_MOVING, MV_BIT_RIGHT,
4651 EL_PLAYER_2, ACTION_MOVING, MV_BIT_DOWN,
4655 EL_PLAYER_2, ACTION_MOVING, MV_BIT_LEFT,
4659 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_UP,
4663 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_RIGHT,
4667 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_DOWN,
4671 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_LEFT,
4675 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_UP,
4679 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_RIGHT,
4683 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_DOWN,
4687 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_LEFT,
4691 EL_PLAYER_1, ACTION_DEFAULT, -1,
4695 EL_PLAYER_2, ACTION_DEFAULT, -1,
4704 int map_element_RND_to_EM(int element_rnd)
4706 static unsigned short mapping_RND_to_EM[NUM_FILE_ELEMENTS];
4707 static boolean mapping_initialized = FALSE;
4709 if (!mapping_initialized)
4713 /* return "Xalpha_quest" for all undefined elements in mapping array */
4714 for (i = 0; i < NUM_FILE_ELEMENTS; i++)
4715 mapping_RND_to_EM[i] = Xalpha_quest;
4717 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
4718 if (em_object_mapping_list[i].is_rnd_to_em_mapping)
4719 mapping_RND_to_EM[em_object_mapping_list[i].element_rnd] =
4720 em_object_mapping_list[i].element_em;
4722 mapping_initialized = TRUE;
4725 if (element_rnd >= 0 && element_rnd < NUM_FILE_ELEMENTS)
4726 return mapping_RND_to_EM[element_rnd];
4728 Error(ERR_WARN, "invalid RND level element %d", element_rnd);
4733 int map_element_EM_to_RND(int element_em)
4735 static unsigned short mapping_EM_to_RND[TILE_MAX];
4736 static boolean mapping_initialized = FALSE;
4738 if (!mapping_initialized)
4742 /* return "EL_UNKNOWN" for all undefined elements in mapping array */
4743 for (i = 0; i < TILE_MAX; i++)
4744 mapping_EM_to_RND[i] = EL_UNKNOWN;
4746 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
4747 mapping_EM_to_RND[em_object_mapping_list[i].element_em] =
4748 em_object_mapping_list[i].element_rnd;
4750 mapping_initialized = TRUE;
4753 if (element_em >= 0 && element_em < TILE_MAX)
4754 return mapping_EM_to_RND[element_em];
4756 Error(ERR_WARN, "invalid EM level element %d", element_em);
4763 int map_element_RND_to_EM(int element_rnd)
4765 static unsigned short mapping_RND_to_EM[NUM_FILE_ELEMENTS];
4766 static boolean mapping_initialized = FALSE;
4773 mapping_RND_to_EM_list[] =
4775 { Xblank, EL_EMPTY },
4776 { Xstone, EL_ROCK },
4778 { Xbug_n, EL_BUG_UP },
4779 { Xbug_e, EL_BUG_RIGHT },
4780 { Xbug_s, EL_BUG_DOWN },
4781 { Xbug_w, EL_BUG_LEFT },
4782 { Xtank_n, EL_SPACESHIP_UP },
4783 { Xtank_e, EL_SPACESHIP_RIGHT },
4784 { Xtank_s, EL_SPACESHIP_DOWN },
4785 { Xtank_w, EL_SPACESHIP_LEFT },
4786 { Xandroid, EL_EMC_ANDROID },
4787 { Xandroid_1_n, EL_EMC_ANDROID_UP },
4788 { Xandroid_1_e, EL_EMC_ANDROID_RIGHT },
4789 { Xandroid_1_w, EL_EMC_ANDROID_LEFT },
4790 { Xandroid_1_s, EL_EMC_ANDROID_DOWN },
4791 { Xspring, EL_SPRING },
4792 { Xeater_n, EL_YAMYAM },
4793 { Xalien, EL_ROBOT },
4794 { Xemerald, EL_EMERALD },
4795 { Xdiamond, EL_DIAMOND },
4796 { Xdrip_fall, EL_AMOEBA_DROP },
4798 { Xballoon, EL_BALLOON },
4799 { Xgrass, EL_EMC_GRASS },
4801 { Xacid_ne, EL_ACID_POOL_TOPRIGHT },
4802 { Xacid_se, EL_ACID_POOL_BOTTOMRIGHT },
4803 { Xacid_s, EL_ACID_POOL_BOTTOM },
4804 { Xacid_sw, EL_ACID_POOL_BOTTOMLEFT },
4805 { Xacid_nw, EL_ACID_POOL_TOPLEFT },
4806 { Xacid_1, EL_ACID },
4807 { Xball_1, EL_EMC_MAGIC_BALL },
4808 { Xgrow_ns, EL_EMC_GROW },
4809 { Xwonderwall, EL_MAGIC_WALL },
4810 { Xamoeba_1, EL_AMOEBA_WET },
4811 { Xdoor_1, EL_EM_GATE_1 },
4812 { Xdoor_2, EL_EM_GATE_2 },
4813 { Xdoor_3, EL_EM_GATE_3 },
4814 { Xdoor_4, EL_EM_GATE_4 },
4815 { Xdoor_5, EL_EMC_GATE_5 },
4816 { Xdoor_6, EL_EMC_GATE_6 },
4817 { Xdoor_7, EL_EMC_GATE_7 },
4818 { Xdoor_8, EL_EMC_GATE_8 },
4819 { Xkey_1, EL_EM_KEY_1 },
4820 { Xkey_2, EL_EM_KEY_2 },
4821 { Xkey_3, EL_EM_KEY_3 },
4822 { Xkey_4, EL_EM_KEY_4 },
4823 { Xkey_5, EL_EMC_KEY_5 },
4824 { Xkey_6, EL_EMC_KEY_6 },
4825 { Xkey_7, EL_EMC_KEY_7 },
4826 { Xkey_8, EL_EMC_KEY_8 },
4827 { Xwind_n, EL_BALLOON_SWITCH_UP },
4828 { Xwind_e, EL_BALLOON_SWITCH_RIGHT },
4829 { Xwind_s, EL_BALLOON_SWITCH_DOWN },
4830 { Xwind_w, EL_BALLOON_SWITCH_LEFT },
4831 { Xwind_nesw, EL_BALLOON_SWITCH_ANY },
4832 { Xwind_stop, EL_BALLOON_SWITCH_NONE },
4833 { Xexit, EL_EXIT_CLOSED },
4834 { Xexit_1, EL_EXIT_OPEN },
4835 { Xdynamite, EL_DYNAMITE },
4836 { Xdynamite_1, EL_DYNAMITE_ACTIVE },
4837 { Xbumper, EL_EMC_BUMPER },
4838 { Xwheel, EL_ROBOT_WHEEL },
4839 { Xswitch, EL_UNKNOWN },
4840 { Xsand, EL_QUICKSAND_EMPTY },
4841 { Xsand_stone, EL_QUICKSAND_FULL },
4842 { Xplant, EL_EMC_PLANT },
4843 { Xlenses, EL_EMC_LENSES },
4844 { Xmagnify, EL_EMC_MAGNIFIER },
4845 { Xdripper, EL_UNKNOWN },
4846 { Xfake_blank, EL_INVISIBLE_WALL },
4847 { Xfake_grass, EL_INVISIBLE_SAND },
4848 { Xfake_door_1, EL_EM_GATE_1_GRAY },
4849 { Xfake_door_2, EL_EM_GATE_2_GRAY },
4850 { Xfake_door_3, EL_EM_GATE_3_GRAY },
4851 { Xfake_door_4, EL_EM_GATE_4_GRAY },
4852 { Xfake_door_5, EL_EMC_GATE_5_GRAY },
4853 { Xfake_door_6, EL_EMC_GATE_6_GRAY },
4854 { Xfake_door_7, EL_EMC_GATE_7_GRAY },
4855 { Xfake_door_8, EL_EMC_GATE_8_GRAY },
4856 { Xsteel_1, EL_STEELWALL },
4857 { Xsteel_2, EL_UNKNOWN },
4858 { Xsteel_3, EL_EMC_STEELWALL_1 },
4859 { Xsteel_4, EL_UNKNOWN },
4860 { Xwall_1, EL_WALL },
4861 { Xwall_2, EL_UNKNOWN },
4862 { Xwall_3, EL_UNKNOWN },
4863 { Xwall_4, EL_UNKNOWN },
4864 { Xround_wall_1, EL_WALL_SLIPPERY },
4865 { Xround_wall_2, EL_UNKNOWN },
4866 { Xround_wall_3, EL_UNKNOWN },
4867 { Xround_wall_4, EL_UNKNOWN },
4868 { Xdecor_1, EL_UNKNOWN },
4869 { Xdecor_2, EL_EMC_WALL_6 },
4870 { Xdecor_3, EL_EMC_WALL_4 },
4871 { Xdecor_4, EL_EMC_WALL_5 },
4872 { Xdecor_5, EL_EMC_WALL_7 },
4873 { Xdecor_6, EL_EMC_WALL_8 },
4874 { Xdecor_7, EL_UNKNOWN },
4875 { Xdecor_8, EL_EMC_WALL_1 },
4876 { Xdecor_9, EL_EMC_WALL_2 },
4877 { Xdecor_10, EL_EMC_WALL_3 },
4878 { Xdecor_11, EL_UNKNOWN },
4879 { Xdecor_12, EL_UNKNOWN },
4880 { Xalpha_0, EL_CHAR('0') },
4881 { Xalpha_1, EL_CHAR('1') },
4882 { Xalpha_2, EL_CHAR('2') },
4883 { Xalpha_3, EL_CHAR('3') },
4884 { Xalpha_4, EL_CHAR('4') },
4885 { Xalpha_5, EL_CHAR('5') },
4886 { Xalpha_6, EL_CHAR('6') },
4887 { Xalpha_7, EL_CHAR('7') },
4888 { Xalpha_8, EL_CHAR('8') },
4889 { Xalpha_9, EL_CHAR('9') },
4890 { Xalpha_excla, EL_CHAR('!') },
4891 { Xalpha_quote, EL_CHAR('"') },
4892 { Xalpha_comma, EL_CHAR(',') },
4893 { Xalpha_minus, EL_CHAR('-') },
4894 { Xalpha_perio, EL_CHAR('.') },
4895 { Xalpha_colon, EL_CHAR(':') },
4896 { Xalpha_quest, EL_CHAR('?') },
4897 { Xalpha_a, EL_CHAR('A') },
4898 { Xalpha_b, EL_CHAR('B') },
4899 { Xalpha_c, EL_CHAR('C') },
4900 { Xalpha_d, EL_CHAR('D') },
4901 { Xalpha_e, EL_CHAR('E') },
4902 { Xalpha_f, EL_CHAR('F') },
4903 { Xalpha_g, EL_CHAR('G') },
4904 { Xalpha_h, EL_CHAR('H') },
4905 { Xalpha_i, EL_CHAR('I') },
4906 { Xalpha_j, EL_CHAR('J') },
4907 { Xalpha_k, EL_CHAR('K') },
4908 { Xalpha_l, EL_CHAR('L') },
4909 { Xalpha_m, EL_CHAR('M') },
4910 { Xalpha_n, EL_CHAR('N') },
4911 { Xalpha_o, EL_CHAR('O') },
4912 { Xalpha_p, EL_CHAR('P') },
4913 { Xalpha_q, EL_CHAR('Q') },
4914 { Xalpha_r, EL_CHAR('R') },
4915 { Xalpha_s, EL_CHAR('S') },
4916 { Xalpha_t, EL_CHAR('T') },
4917 { Xalpha_u, EL_CHAR('U') },
4918 { Xalpha_v, EL_CHAR('V') },
4919 { Xalpha_w, EL_CHAR('W') },
4920 { Xalpha_x, EL_CHAR('X') },
4921 { Xalpha_y, EL_CHAR('Y') },
4922 { Xalpha_z, EL_CHAR('Z') },
4923 { Xalpha_arrow_e, EL_CHAR('>') },
4924 { Xalpha_arrow_w, EL_CHAR('<') },
4925 { Xalpha_copyr, EL_CHAR('©') },
4927 { Zplayer, EL_PLAYER_1 },
4928 { Zplayer, EL_PLAYER_2 },
4929 { Zplayer, EL_PLAYER_3 },
4930 { Zplayer, EL_PLAYER_4 },
4932 { ZBORDER, EL_EMC_LEVEL_BORDER },
4937 if (!mapping_initialized)
4941 /* return "Xalpha_quest" for all undefined elements in mapping array */
4942 for (i = 0; i < NUM_FILE_ELEMENTS; i++)
4943 mapping_RND_to_EM[i] = Xalpha_quest;
4945 for (i = 0; mapping_RND_to_EM_list[i].element_rnd != -1; i++)
4946 mapping_RND_to_EM[mapping_RND_to_EM_list[i].element_rnd] =
4947 mapping_RND_to_EM_list[i].element_em;
4949 mapping_initialized = TRUE;
4952 if (element_rnd >= 0 && element_rnd < NUM_FILE_ELEMENTS)
4953 return mapping_RND_to_EM[element_rnd];
4955 Error(ERR_WARN, "invalid RND level element %d", element_rnd);
4960 int map_element_EM_to_RND(int element_em)
4962 static unsigned short mapping_EM_to_RND[TILE_MAX];
4963 static boolean mapping_initialized = FALSE;
4970 em_object_mapping_list[] =
4972 { Xblank, EL_EMPTY },
4973 { Yacid_splash_eB, EL_EMPTY },
4974 { Yacid_splash_wB, EL_EMPTY },
4976 #ifdef EM_ENGINE_BAD_ROLL
4977 { Xstone_force_e, EL_ROCK },
4978 { Xstone_force_w, EL_ROCK },
4979 { Xnut_force_e, EL_NUT },
4980 { Xnut_force_w, EL_NUT },
4981 { Xspring_force_e, EL_SPRING },
4982 { Xspring_force_w, EL_SPRING },
4983 { Xemerald_force_e, EL_EMERALD },
4984 { Xemerald_force_w, EL_EMERALD },
4985 { Xdiamond_force_e, EL_DIAMOND },
4986 { Xdiamond_force_w, EL_DIAMOND },
4987 { Xbomb_force_e, EL_BOMB },
4988 { Xbomb_force_w, EL_BOMB },
4991 { Xstone, EL_ROCK },
4992 { Xstone_pause, EL_ROCK },
4993 { Xstone_fall, EL_ROCK },
4994 { Ystone_s, EL_ROCK },
4995 { Ystone_sB, EL_ROCK },
4996 { Ystone_e, EL_ROCK },
4997 { Ystone_eB, EL_ROCK },
4998 { Ystone_w, EL_ROCK },
4999 { Ystone_wB, EL_ROCK },
5001 { Xnut_pause, EL_NUT },
5002 { Xnut_fall, EL_NUT },
5004 { Ynut_sB, EL_NUT },
5006 { Ynut_eB, EL_NUT },
5008 { Ynut_wB, EL_NUT },
5009 { Xbug_n, EL_BUG_UP },
5010 { Xbug_e, EL_BUG_RIGHT },
5011 { Xbug_s, EL_BUG_DOWN },
5012 { Xbug_w, EL_BUG_LEFT },
5013 { Xbug_gon, EL_BUG_UP },
5014 { Xbug_goe, EL_BUG_RIGHT },
5015 { Xbug_gos, EL_BUG_DOWN },
5016 { Xbug_gow, EL_BUG_LEFT },
5017 { Ybug_n, EL_BUG_UP },
5018 { Ybug_nB, EL_BUG_UP },
5019 { Ybug_e, EL_BUG_RIGHT },
5020 { Ybug_eB, EL_BUG_RIGHT },
5021 { Ybug_s, EL_BUG_DOWN },
5022 { Ybug_sB, EL_BUG_DOWN },
5023 { Ybug_w, EL_BUG_LEFT },
5024 { Ybug_wB, EL_BUG_LEFT },
5025 { Ybug_w_n, EL_BUG_UP },
5026 { Ybug_n_e, EL_BUG_RIGHT },
5027 { Ybug_e_s, EL_BUG_DOWN },
5028 { Ybug_s_w, EL_BUG_LEFT },
5029 { Ybug_e_n, EL_BUG_UP },
5030 { Ybug_s_e, EL_BUG_RIGHT },
5031 { Ybug_w_s, EL_BUG_DOWN },
5032 { Ybug_n_w, EL_BUG_LEFT },
5033 { Ybug_stone, EL_ROCK },
5034 { Ybug_spring, EL_SPRING },
5035 { Xtank_n, EL_SPACESHIP_UP },
5036 { Xtank_e, EL_SPACESHIP_RIGHT },
5037 { Xtank_s, EL_SPACESHIP_DOWN },
5038 { Xtank_w, EL_SPACESHIP_LEFT },
5039 { Xtank_gon, EL_SPACESHIP_UP },
5040 { Xtank_goe, EL_SPACESHIP_RIGHT },
5041 { Xtank_gos, EL_SPACESHIP_DOWN },
5042 { Xtank_gow, EL_SPACESHIP_LEFT },
5043 { Ytank_n, EL_SPACESHIP_UP },
5044 { Ytank_nB, EL_SPACESHIP_UP },
5045 { Ytank_e, EL_SPACESHIP_RIGHT },
5046 { Ytank_eB, EL_SPACESHIP_RIGHT },
5047 { Ytank_s, EL_SPACESHIP_DOWN },
5048 { Ytank_sB, EL_SPACESHIP_DOWN },
5049 { Ytank_w, EL_SPACESHIP_LEFT },
5050 { Ytank_wB, EL_SPACESHIP_LEFT },
5051 { Ytank_w_n, EL_SPACESHIP_UP },
5052 { Ytank_n_e, EL_SPACESHIP_RIGHT },
5053 { Ytank_e_s, EL_SPACESHIP_DOWN },
5054 { Ytank_s_w, EL_SPACESHIP_LEFT },
5055 { Ytank_e_n, EL_SPACESHIP_UP },
5056 { Ytank_s_e, EL_SPACESHIP_RIGHT },
5057 { Ytank_w_s, EL_SPACESHIP_DOWN },
5058 { Ytank_n_w, EL_SPACESHIP_LEFT },
5059 { Ytank_stone, EL_ROCK },
5060 { Ytank_spring, EL_SPRING },
5061 { Xandroid, EL_EMC_ANDROID },
5062 { Xandroid_1_n, EL_EMC_ANDROID_UP },
5063 { Xandroid_2_n, EL_EMC_ANDROID_UP },
5064 { Xandroid_1_e, EL_EMC_ANDROID_RIGHT },
5065 { Xandroid_2_e, EL_EMC_ANDROID_RIGHT },
5066 { Xandroid_1_w, EL_EMC_ANDROID_LEFT },
5067 { Xandroid_2_w, EL_EMC_ANDROID_LEFT },
5068 { Xandroid_1_s, EL_EMC_ANDROID_DOWN },
5069 { Xandroid_2_s, EL_EMC_ANDROID_DOWN },
5070 { Yandroid_n, EL_EMC_ANDROID_UP },
5071 { Yandroid_nB, EL_EMC_ANDROID_UP },
5072 { Yandroid_ne, EL_EMC_ANDROID_RIGHT_UP },
5073 { Yandroid_neB, EL_EMC_ANDROID_RIGHT_UP },
5074 { Yandroid_e, EL_EMC_ANDROID_RIGHT },
5075 { Yandroid_eB, EL_EMC_ANDROID_RIGHT },
5076 { Yandroid_se, EL_EMC_ANDROID_RIGHT_DOWN },
5077 { Yandroid_seB, EL_EMC_ANDROID_RIGHT_DOWN },
5078 { Yandroid_s, EL_EMC_ANDROID_DOWN },
5079 { Yandroid_sB, EL_EMC_ANDROID_DOWN },
5080 { Yandroid_sw, EL_EMC_ANDROID_LEFT_DOWN },
5081 { Yandroid_swB, EL_EMC_ANDROID_LEFT_DOWN },
5082 { Yandroid_w, EL_EMC_ANDROID_LEFT },
5083 { Yandroid_wB, EL_EMC_ANDROID_LEFT },
5084 { Yandroid_nw, EL_EMC_ANDROID_LEFT_UP },
5085 { Yandroid_nwB, EL_EMC_ANDROID_LEFT_UP },
5086 { Xspring, EL_SPRING },
5087 { Xspring_pause, EL_SPRING },
5088 { Xspring_e, EL_SPRING },
5089 { Xspring_w, EL_SPRING },
5090 { Xspring_fall, EL_SPRING },
5091 { Yspring_s, EL_SPRING },
5092 { Yspring_sB, EL_SPRING },
5093 { Yspring_e, EL_SPRING },
5094 { Yspring_eB, EL_SPRING },
5095 { Yspring_w, EL_SPRING },
5096 { Yspring_wB, EL_SPRING },
5097 { Yspring_kill_e, EL_SPRING },
5098 { Yspring_kill_eB, EL_SPRING },
5099 { Yspring_kill_w, EL_SPRING },
5100 { Yspring_kill_wB, EL_SPRING },
5101 { Xeater_n, EL_YAMYAM },
5102 { Xeater_e, EL_YAMYAM },
5103 { Xeater_w, EL_YAMYAM },
5104 { Xeater_s, EL_YAMYAM },
5105 { Yeater_n, EL_YAMYAM },
5106 { Yeater_nB, EL_YAMYAM },
5107 { Yeater_e, EL_YAMYAM },
5108 { Yeater_eB, EL_YAMYAM },
5109 { Yeater_s, EL_YAMYAM },
5110 { Yeater_sB, EL_YAMYAM },
5111 { Yeater_w, EL_YAMYAM },
5112 { Yeater_wB, EL_YAMYAM },
5113 { Yeater_stone, EL_ROCK },
5114 { Yeater_spring, EL_SPRING },
5115 { Xalien, EL_ROBOT },
5116 { Xalien_pause, EL_ROBOT },
5117 { Yalien_n, EL_ROBOT },
5118 { Yalien_nB, EL_ROBOT },
5119 { Yalien_e, EL_ROBOT },
5120 { Yalien_eB, EL_ROBOT },
5121 { Yalien_s, EL_ROBOT },
5122 { Yalien_sB, EL_ROBOT },
5123 { Yalien_w, EL_ROBOT },
5124 { Yalien_wB, EL_ROBOT },
5125 { Yalien_stone, EL_ROCK },
5126 { Yalien_spring, EL_SPRING },
5127 { Xemerald, EL_EMERALD },
5128 { Xemerald_pause, EL_EMERALD },
5129 { Xemerald_fall, EL_EMERALD },
5130 { Xemerald_shine, EL_EMERALD },
5131 { Yemerald_s, EL_EMERALD },
5132 { Yemerald_sB, EL_EMERALD },
5133 { Yemerald_e, EL_EMERALD },
5134 { Yemerald_eB, EL_EMERALD },
5135 { Yemerald_w, EL_EMERALD },
5136 { Yemerald_wB, EL_EMERALD },
5137 { Yemerald_eat, EL_EMERALD },
5138 { Yemerald_stone, EL_ROCK },
5139 { Xdiamond, EL_DIAMOND },
5140 { Xdiamond_pause, EL_DIAMOND },
5141 { Xdiamond_fall, EL_DIAMOND },
5142 { Xdiamond_shine, EL_DIAMOND },
5143 { Ydiamond_s, EL_DIAMOND },
5144 { Ydiamond_sB, EL_DIAMOND },
5145 { Ydiamond_e, EL_DIAMOND },
5146 { Ydiamond_eB, EL_DIAMOND },
5147 { Ydiamond_w, EL_DIAMOND },
5148 { Ydiamond_wB, EL_DIAMOND },
5149 { Ydiamond_eat, EL_DIAMOND },
5150 { Ydiamond_stone, EL_ROCK },
5151 { Xdrip_fall, EL_AMOEBA_DROP },
5152 { Xdrip_stretch, EL_AMOEBA_DROP },
5153 { Xdrip_stretchB, EL_AMOEBA_DROP },
5154 { Xdrip_eat, EL_AMOEBA_DROP },
5155 { Ydrip_s1, EL_AMOEBA_DROP },
5156 { Ydrip_s1B, EL_AMOEBA_DROP },
5157 { Ydrip_s2, EL_AMOEBA_DROP },
5158 { Ydrip_s2B, EL_AMOEBA_DROP },
5160 { Xbomb_pause, EL_BOMB },
5161 { Xbomb_fall, EL_BOMB },
5162 { Ybomb_s, EL_BOMB },
5163 { Ybomb_sB, EL_BOMB },
5164 { Ybomb_e, EL_BOMB },
5165 { Ybomb_eB, EL_BOMB },
5166 { Ybomb_w, EL_BOMB },
5167 { Ybomb_wB, EL_BOMB },
5168 { Ybomb_eat, EL_BOMB },
5169 { Xballoon, EL_BALLOON },
5170 { Yballoon_n, EL_BALLOON },
5171 { Yballoon_nB, EL_BALLOON },
5172 { Yballoon_e, EL_BALLOON },
5173 { Yballoon_eB, EL_BALLOON },
5174 { Yballoon_s, EL_BALLOON },
5175 { Yballoon_sB, EL_BALLOON },
5176 { Yballoon_w, EL_BALLOON },
5177 { Yballoon_wB, EL_BALLOON },
5178 { Xgrass, EL_SAND },
5179 { Ygrass_nB, EL_SAND },
5180 { Ygrass_eB, EL_SAND },
5181 { Ygrass_sB, EL_SAND },
5182 { Ygrass_wB, EL_SAND },
5184 { Ydirt_nB, EL_SAND },
5185 { Ydirt_eB, EL_SAND },
5186 { Ydirt_sB, EL_SAND },
5187 { Ydirt_wB, EL_SAND },
5188 { Xacid_ne, EL_ACID_POOL_TOPRIGHT },
5189 { Xacid_se, EL_ACID_POOL_BOTTOMRIGHT },
5190 { Xacid_s, EL_ACID_POOL_BOTTOM },
5191 { Xacid_sw, EL_ACID_POOL_BOTTOMLEFT },
5192 { Xacid_nw, EL_ACID_POOL_TOPLEFT },
5193 { Xacid_1, EL_ACID },
5194 { Xacid_2, EL_ACID },
5195 { Xacid_3, EL_ACID },
5196 { Xacid_4, EL_ACID },
5197 { Xacid_5, EL_ACID },
5198 { Xacid_6, EL_ACID },
5199 { Xacid_7, EL_ACID },
5200 { Xacid_8, EL_ACID },
5201 { Xball_1, EL_EMC_MAGIC_BALL },
5202 { Xball_1B, EL_EMC_MAGIC_BALL },
5203 { Xball_2, EL_EMC_MAGIC_BALL },
5204 { Xball_2B, EL_EMC_MAGIC_BALL },
5205 { Yball_eat, EL_EMC_MAGIC_BALL },
5206 { Xgrow_ns, EL_EMC_GROW },
5207 { Ygrow_ns_eat, EL_EMC_GROW },
5208 { Xgrow_ew, EL_EMC_GROW },
5209 { Ygrow_ew_eat, EL_EMC_GROW },
5210 { Xwonderwall, EL_MAGIC_WALL },
5211 { XwonderwallB, EL_MAGIC_WALL },
5212 { Xamoeba_1, EL_AMOEBA_WET },
5213 { Xamoeba_2, EL_AMOEBA_WET },
5214 { Xamoeba_3, EL_AMOEBA_WET },
5215 { Xamoeba_4, EL_AMOEBA_WET },
5216 { Xamoeba_5, EL_AMOEBA_WET },
5217 { Xamoeba_6, EL_AMOEBA_WET },
5218 { Xamoeba_7, EL_AMOEBA_WET },
5219 { Xamoeba_8, EL_AMOEBA_WET },
5220 { Xdoor_1, EL_EM_GATE_1 },
5221 { Xdoor_2, EL_EM_GATE_2 },
5222 { Xdoor_3, EL_EM_GATE_3 },
5223 { Xdoor_4, EL_EM_GATE_4 },
5224 { Xdoor_5, EL_EMC_GATE_5 },
5225 { Xdoor_6, EL_EMC_GATE_6 },
5226 { Xdoor_7, EL_EMC_GATE_7 },
5227 { Xdoor_8, EL_EMC_GATE_8 },
5228 { Xkey_1, EL_EM_KEY_1 },
5229 { Xkey_2, EL_EM_KEY_2 },
5230 { Xkey_3, EL_EM_KEY_3 },
5231 { Xkey_4, EL_EM_KEY_4 },
5232 { Xkey_5, EL_EMC_KEY_5 },
5233 { Xkey_6, EL_EMC_KEY_6 },
5234 { Xkey_7, EL_EMC_KEY_7 },
5235 { Xkey_8, EL_EMC_KEY_8 },
5236 { Xwind_n, EL_BALLOON_SWITCH_UP },
5237 { Xwind_e, EL_BALLOON_SWITCH_RIGHT },
5238 { Xwind_s, EL_BALLOON_SWITCH_DOWN },
5239 { Xwind_w, EL_BALLOON_SWITCH_LEFT },
5240 { Xwind_nesw, EL_BALLOON_SWITCH_ANY },
5241 { Xwind_stop, EL_BALLOON_SWITCH_NONE },
5242 { Xexit, EL_EXIT_CLOSED },
5243 { Xexit_1, EL_EXIT_OPEN },
5244 { Xexit_2, EL_EXIT_OPEN },
5245 { Xexit_3, EL_EXIT_OPEN },
5246 { Xdynamite, EL_DYNAMITE },
5247 { Ydynamite_eat, EL_DYNAMITE },
5248 { Xdynamite_1, EL_DYNAMITE_ACTIVE },
5249 { Xdynamite_2, EL_DYNAMITE_ACTIVE },
5250 { Xdynamite_3, EL_DYNAMITE_ACTIVE },
5251 { Xdynamite_4, EL_DYNAMITE_ACTIVE },
5252 { Xbumper, EL_EMC_BUMPER },
5253 { XbumperB, EL_EMC_BUMPER },
5254 { Xwheel, EL_ROBOT_WHEEL },
5255 { XwheelB, EL_ROBOT_WHEEL },
5256 { Xswitch, EL_UNKNOWN },
5257 { XswitchB, EL_UNKNOWN },
5258 { Xsand, EL_QUICKSAND_EMPTY },
5259 { Xsand_stone, EL_QUICKSAND_FULL },
5260 { Xsand_stonein_1, EL_QUICKSAND_FULL },
5261 { Xsand_stonein_2, EL_QUICKSAND_FULL },
5262 { Xsand_stonein_3, EL_QUICKSAND_FULL },
5263 { Xsand_stonein_4, EL_QUICKSAND_FULL },
5264 { Xsand_stonesand_1, EL_QUICKSAND_FULL },
5265 { Xsand_stonesand_2, EL_QUICKSAND_FULL },
5266 { Xsand_stonesand_3, EL_QUICKSAND_FULL },
5267 { Xsand_stonesand_4, EL_QUICKSAND_FULL },
5268 { Xsand_stoneout_1, EL_QUICKSAND_FULL },
5269 { Xsand_stoneout_2, EL_QUICKSAND_FULL },
5270 { Xsand_sandstone_1, EL_QUICKSAND_FULL },
5271 { Xsand_sandstone_2, EL_QUICKSAND_FULL },
5272 { Xsand_sandstone_3, EL_QUICKSAND_FULL },
5273 { Xsand_sandstone_4, EL_QUICKSAND_FULL },
5274 { Xplant, EL_EMC_PLANT },
5275 { Yplant, EL_EMC_PLANT },
5276 { Xlenses, EL_EMC_LENSES },
5277 { Xmagnify, EL_EMC_MAGNIFIER },
5278 { Xdripper, EL_UNKNOWN },
5279 { XdripperB, EL_UNKNOWN },
5280 { Xfake_blank, EL_INVISIBLE_WALL },
5281 { Xfake_blankB, EL_INVISIBLE_WALL },
5282 { Xfake_grass, EL_INVISIBLE_SAND },
5283 { Xfake_grassB, EL_INVISIBLE_SAND },
5284 { Xfake_door_1, EL_EM_GATE_1_GRAY },
5285 { Xfake_door_2, EL_EM_GATE_2_GRAY },
5286 { Xfake_door_3, EL_EM_GATE_3_GRAY },
5287 { Xfake_door_4, EL_EM_GATE_4_GRAY },
5288 { Xfake_door_5, EL_EMC_GATE_5_GRAY },
5289 { Xfake_door_6, EL_EMC_GATE_6_GRAY },
5290 { Xfake_door_7, EL_EMC_GATE_7_GRAY },
5291 { Xfake_door_8, EL_EMC_GATE_8_GRAY },
5292 { Xsteel_1, EL_STEELWALL },
5293 { Xsteel_2, EL_UNKNOWN },
5294 { Xsteel_3, EL_EMC_STEELWALL_1 },
5295 { Xsteel_4, EL_UNKNOWN },
5296 { Xwall_1, EL_WALL },
5297 { Xwall_2, EL_UNKNOWN },
5298 { Xwall_3, EL_UNKNOWN },
5299 { Xwall_4, EL_UNKNOWN },
5300 { Xround_wall_1, EL_WALL_SLIPPERY },
5301 { Xround_wall_2, EL_UNKNOWN },
5302 { Xround_wall_3, EL_UNKNOWN },
5303 { Xround_wall_4, EL_UNKNOWN },
5304 { Xdecor_1, EL_UNKNOWN },
5305 { Xdecor_2, EL_EMC_WALL_6 },
5306 { Xdecor_3, EL_EMC_WALL_4 },
5307 { Xdecor_4, EL_EMC_WALL_5 },
5308 { Xdecor_5, EL_EMC_WALL_7 },
5309 { Xdecor_6, EL_EMC_WALL_8 },
5310 { Xdecor_7, EL_UNKNOWN },
5311 { Xdecor_8, EL_EMC_WALL_1 },
5312 { Xdecor_9, EL_EMC_WALL_2 },
5313 { Xdecor_10, EL_EMC_WALL_3 },
5314 { Xdecor_11, EL_UNKNOWN },
5315 { Xdecor_12, EL_UNKNOWN },
5316 { Xalpha_0, EL_CHAR('0') },
5317 { Xalpha_1, EL_CHAR('1') },
5318 { Xalpha_2, EL_CHAR('2') },
5319 { Xalpha_3, EL_CHAR('3') },
5320 { Xalpha_4, EL_CHAR('4') },
5321 { Xalpha_5, EL_CHAR('5') },
5322 { Xalpha_6, EL_CHAR('6') },
5323 { Xalpha_7, EL_CHAR('7') },
5324 { Xalpha_8, EL_CHAR('8') },
5325 { Xalpha_9, EL_CHAR('9') },
5326 { Xalpha_excla, EL_CHAR('!') },
5327 { Xalpha_quote, EL_CHAR('"') },
5328 { Xalpha_comma, EL_CHAR(',') },
5329 { Xalpha_minus, EL_CHAR('-') },
5330 { Xalpha_perio, EL_CHAR('.') },
5331 { Xalpha_colon, EL_CHAR(':') },
5332 { Xalpha_quest, EL_CHAR('?') },
5333 { Xalpha_a, EL_CHAR('A') },
5334 { Xalpha_b, EL_CHAR('B') },
5335 { Xalpha_c, EL_CHAR('C') },
5336 { Xalpha_d, EL_CHAR('D') },
5337 { Xalpha_e, EL_CHAR('E') },
5338 { Xalpha_f, EL_CHAR('F') },
5339 { Xalpha_g, EL_CHAR('G') },
5340 { Xalpha_h, EL_CHAR('H') },
5341 { Xalpha_i, EL_CHAR('I') },
5342 { Xalpha_j, EL_CHAR('J') },
5343 { Xalpha_k, EL_CHAR('K') },
5344 { Xalpha_l, EL_CHAR('L') },
5345 { Xalpha_m, EL_CHAR('M') },
5346 { Xalpha_n, EL_CHAR('N') },
5347 { Xalpha_o, EL_CHAR('O') },
5348 { Xalpha_p, EL_CHAR('P') },
5349 { Xalpha_q, EL_CHAR('Q') },
5350 { Xalpha_r, EL_CHAR('R') },
5351 { Xalpha_s, EL_CHAR('S') },
5352 { Xalpha_t, EL_CHAR('T') },
5353 { Xalpha_u, EL_CHAR('U') },
5354 { Xalpha_v, EL_CHAR('V') },
5355 { Xalpha_w, EL_CHAR('W') },
5356 { Xalpha_x, EL_CHAR('X') },
5357 { Xalpha_y, EL_CHAR('Y') },
5358 { Xalpha_z, EL_CHAR('Z') },
5359 { Xalpha_arrow_e, EL_CHAR('>') },
5360 { Xalpha_arrow_w, EL_CHAR('<') },
5361 { Xalpha_copyr, EL_CHAR('©') },
5363 { Zplayer, EL_PLAYER_1 },
5365 { ZBORDER, EL_EMC_LEVEL_BORDER },
5370 if (!mapping_initialized)
5374 /* return "EL_UNKNOWN" for all undefined elements in mapping array */
5375 for (i = 0; i < TILE_MAX; i++)
5376 mapping_EM_to_RND[i] = EL_UNKNOWN;
5378 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
5379 mapping_EM_to_RND[em_object_mapping_list[i].element_em] =
5380 em_object_mapping_list[i].element_rnd;
5382 mapping_initialized = TRUE;
5385 if (element_em >= 0 && element_em < TILE_MAX)
5386 return mapping_EM_to_RND[element_em];
5388 Error(ERR_WARN, "invalid EM level element %d", element_em);
5395 int get_next_element(int element)
5399 case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL;
5400 case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY;
5401 case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL;
5402 case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_ACTIVE;
5403 case EL_BD_MAGIC_WALL_FILLING: return EL_BD_MAGIC_WALL_FULL;
5404 case EL_BD_MAGIC_WALL_EMPTYING: return EL_BD_MAGIC_WALL_ACTIVE;
5405 case EL_AMOEBA_DROPPING: return EL_AMOEBA_WET;
5407 default: return element;
5412 int el_act_dir2img(int element, int action, int direction)
5414 element = GFX_ELEMENT(element);
5416 if (direction == MV_NONE)
5417 return element_info[element].graphic[action];
5419 direction = MV_DIR_BIT(direction);
5421 return element_info[element].direction_graphic[action][direction];
5424 int el_act_dir2img(int element, int action, int direction)
5426 element = GFX_ELEMENT(element);
5427 direction = MV_DIR_BIT(direction); /* default: MV_NONE => MV_DOWN */
5429 /* direction_graphic[][] == graphic[] for undefined direction graphics */
5430 return element_info[element].direction_graphic[action][direction];
5435 static int el_act_dir2crm(int element, int action, int direction)
5437 element = GFX_ELEMENT(element);
5439 if (direction == MV_NONE)
5440 return element_info[element].crumbled[action];
5442 direction = MV_DIR_BIT(direction);
5444 return element_info[element].direction_crumbled[action][direction];
5447 static int el_act_dir2crm(int element, int action, int direction)
5449 element = GFX_ELEMENT(element);
5450 direction = MV_DIR_BIT(direction); /* default: MV_NONE => MV_DOWN */
5452 /* direction_graphic[][] == graphic[] for undefined direction graphics */
5453 return element_info[element].direction_crumbled[action][direction];
5457 int el_act2img(int element, int action)
5459 element = GFX_ELEMENT(element);
5461 return element_info[element].graphic[action];
5464 int el_act2crm(int element, int action)
5466 element = GFX_ELEMENT(element);
5468 return element_info[element].crumbled[action];
5471 int el_dir2img(int element, int direction)
5473 element = GFX_ELEMENT(element);
5475 return el_act_dir2img(element, ACTION_DEFAULT, direction);
5478 int el2baseimg(int element)
5480 return element_info[element].graphic[ACTION_DEFAULT];
5483 int el2img(int element)
5485 element = GFX_ELEMENT(element);
5487 return element_info[element].graphic[ACTION_DEFAULT];
5490 int el2edimg(int element)
5492 element = GFX_ELEMENT(element);
5494 return element_info[element].special_graphic[GFX_SPECIAL_ARG_EDITOR];
5497 int el2preimg(int element)
5499 element = GFX_ELEMENT(element);
5501 return element_info[element].special_graphic[GFX_SPECIAL_ARG_PREVIEW];
5504 int font2baseimg(int font_nr)
5506 return font_info[font_nr].special_graphic[GFX_SPECIAL_ARG_DEFAULT];
5509 int getGameFrameDelay_EM(int native_em_game_frame_delay)
5511 int game_frame_delay_value;
5513 game_frame_delay_value =
5514 (tape.playing && tape.fast_forward ? FfwdFrameDelay :
5515 GameFrameDelay == GAME_FRAME_DELAY ? native_em_game_frame_delay :
5518 if (tape.playing && tape.warp_forward && !tape.pausing)
5519 game_frame_delay_value = 0;
5521 return game_frame_delay_value;
5524 unsigned int InitRND(long seed)
5526 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
5527 return InitEngineRND_EM(seed);
5529 return InitEngineRND(seed);
5532 #define DEBUG_EM_GFX 0
5534 void InitGraphicInfo_EM(void)
5536 struct Mapping_EM_to_RND_object object_mapping[TILE_MAX];
5537 struct Mapping_EM_to_RND_player player_mapping[2][SPR_MAX];
5541 if (graphic_info_em_object[0][0].bitmap == NULL)
5543 /* EM graphics not yet initialized in em_open_all() */
5549 /* always start with reliable default values */
5550 for (i = 0; i < TILE_MAX; i++)
5552 object_mapping[i].element_rnd = EL_UNKNOWN;
5553 object_mapping[i].is_backside = FALSE;
5554 object_mapping[i].action = ACTION_DEFAULT;
5555 object_mapping[i].direction = MV_NONE;
5558 /* always start with reliable default values */
5559 for (p = 0; p < 2; p++)
5561 for (i = 0; i < SPR_MAX; i++)
5563 player_mapping[p][i].element_rnd = EL_UNKNOWN;
5564 player_mapping[p][i].action = ACTION_DEFAULT;
5565 player_mapping[p][i].direction = MV_NONE;
5569 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
5571 int e = em_object_mapping_list[i].element_em;
5573 object_mapping[e].element_rnd = em_object_mapping_list[i].element_rnd;
5574 object_mapping[e].is_backside = em_object_mapping_list[i].is_backside;
5576 if (em_object_mapping_list[i].action != -1)
5577 object_mapping[e].action = em_object_mapping_list[i].action;
5579 if (em_object_mapping_list[i].direction != -1)
5580 object_mapping[e].direction = (1 << em_object_mapping_list[i].direction);
5583 for (i = 0; em_player_mapping_list[i].action_em != -1; i++)
5585 int a = em_player_mapping_list[i].action_em;
5586 int p = em_player_mapping_list[i].player_nr;
5588 player_mapping[p][a].element_rnd = em_player_mapping_list[i].element_rnd;
5590 if (em_player_mapping_list[i].action != -1)
5591 player_mapping[p][a].action = em_player_mapping_list[i].action;
5593 if (em_player_mapping_list[i].direction != -1)
5594 player_mapping[p][a].direction =
5595 (1 << em_player_mapping_list[i].direction);
5598 for (i = 0; i < TILE_MAX; i++)
5600 int element = object_mapping[i].element_rnd;
5601 int action = object_mapping[i].action;
5602 int direction = object_mapping[i].direction;
5603 boolean is_backside = object_mapping[i].is_backside;
5604 boolean action_removing = (action == ACTION_DIGGING ||
5605 action == ACTION_SNAPPING ||
5606 action == ACTION_COLLECTING);
5607 boolean action_exploding = ((action == ACTION_EXPLODING ||
5608 action == ACTION_SMASHED_BY_ROCK ||
5609 action == ACTION_SMASHED_BY_SPRING) &&
5610 element != EL_DIAMOND);
5611 boolean action_active = (action == ACTION_ACTIVE);
5612 boolean action_other = (action == ACTION_OTHER);
5614 for (j = 0; j < 8; j++)
5616 int effective_element = (j > 5 && i == Yacid_splash_eB ? EL_EMPTY :
5617 j > 5 && i == Yacid_splash_wB ? EL_EMPTY :
5619 i == Xdrip_stretch ? element :
5620 i == Xdrip_stretchB ? element :
5621 i == Ydrip_s1 ? element :
5622 i == Ydrip_s1B ? element :
5623 i == Xball_1B ? element :
5624 i == Xball_2 ? element :
5625 i == Xball_2B ? element :
5626 i == Yball_eat ? element :
5627 i == Ykey_1_eat ? element :
5628 i == Ykey_2_eat ? element :
5629 i == Ykey_3_eat ? element :
5630 i == Ykey_4_eat ? element :
5631 i == Ykey_5_eat ? element :
5632 i == Ykey_6_eat ? element :
5633 i == Ykey_7_eat ? element :
5634 i == Ykey_8_eat ? element :
5635 i == Ylenses_eat ? element :
5636 i == Ymagnify_eat ? element :
5637 i == Ygrass_eat ? element :
5638 i == Ydirt_eat ? element :
5639 i == Yspring_kill_e ? EL_SPRING :
5640 i == Yspring_kill_w ? EL_SPRING :
5641 i == Yemerald_stone ? EL_EMERALD :
5642 i == Ydiamond_stone ? EL_ROCK :
5643 i == Xsand_stonein_4 ? EL_EMPTY :
5644 i == Xsand_stoneout_2 ? EL_ROCK :
5645 is_backside ? EL_EMPTY :
5646 action_removing ? EL_EMPTY :
5648 int effective_action = (j < 7 ? action :
5649 i == Xdrip_stretch ? action :
5650 i == Xdrip_stretchB ? action :
5651 i == Ydrip_s1 ? action :
5652 i == Ydrip_s1B ? action :
5653 i == Xball_1B ? action :
5654 i == Xball_2 ? action :
5655 i == Xball_2B ? action :
5656 i == Yball_eat ? action :
5657 i == Ykey_1_eat ? action :
5658 i == Ykey_2_eat ? action :
5659 i == Ykey_3_eat ? action :
5660 i == Ykey_4_eat ? action :
5661 i == Ykey_5_eat ? action :
5662 i == Ykey_6_eat ? action :
5663 i == Ykey_7_eat ? action :
5664 i == Ykey_8_eat ? action :
5665 i == Ylenses_eat ? action :
5666 i == Ymagnify_eat ? action :
5667 i == Ygrass_eat ? action :
5668 i == Ydirt_eat ? action :
5669 i == Xsand_stonein_1 ? action :
5670 i == Xsand_stonein_2 ? action :
5671 i == Xsand_stonein_3 ? action :
5672 i == Xsand_stonein_4 ? action :
5673 i == Xsand_stoneout_1 ? action :
5674 i == Xsand_stoneout_2 ? action :
5675 i == Xboom_android ? ACTION_EXPLODING :
5676 action_exploding ? ACTION_EXPLODING :
5677 action_active ? action :
5678 action_other ? action :
5680 int graphic = (el_act_dir2img(effective_element, effective_action,
5682 int crumbled = (el_act_dir2crm(effective_element, effective_action,
5684 int base_graphic = el_act2img(effective_element, ACTION_DEFAULT);
5685 int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT);
5686 boolean has_crumbled_graphics = (base_crumbled != base_graphic);
5687 struct GraphicInfo *g = &graphic_info[graphic];
5688 struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
5691 /* ensure to get symmetric 3-frame, 2-delay animations as used in EM */
5692 boolean special_animation = (action != ACTION_DEFAULT &&
5693 g->anim_frames == 3 &&
5694 g->anim_delay == 2 &&
5695 g->anim_mode & ANIM_LINEAR);
5696 int sync_frame = (i == Xdrip_stretch ? 7 :
5697 i == Xdrip_stretchB ? 7 :
5698 i == Ydrip_s2 ? j + 8 :
5699 i == Ydrip_s2B ? j + 8 :
5708 i == Xfake_acid_1 ? 0 :
5709 i == Xfake_acid_2 ? 10 :
5710 i == Xfake_acid_3 ? 20 :
5711 i == Xfake_acid_4 ? 30 :
5712 i == Xfake_acid_5 ? 40 :
5713 i == Xfake_acid_6 ? 50 :
5714 i == Xfake_acid_7 ? 60 :
5715 i == Xfake_acid_8 ? 70 :
5717 i == Xball_2B ? j + 8 :
5718 i == Yball_eat ? j + 1 :
5719 i == Ykey_1_eat ? j + 1 :
5720 i == Ykey_2_eat ? j + 1 :
5721 i == Ykey_3_eat ? j + 1 :
5722 i == Ykey_4_eat ? j + 1 :
5723 i == Ykey_5_eat ? j + 1 :
5724 i == Ykey_6_eat ? j + 1 :
5725 i == Ykey_7_eat ? j + 1 :
5726 i == Ykey_8_eat ? j + 1 :
5727 i == Ylenses_eat ? j + 1 :
5728 i == Ymagnify_eat ? j + 1 :
5729 i == Ygrass_eat ? j + 1 :
5730 i == Ydirt_eat ? j + 1 :
5731 i == Xamoeba_1 ? 0 :
5732 i == Xamoeba_2 ? 1 :
5733 i == Xamoeba_3 ? 2 :
5734 i == Xamoeba_4 ? 3 :
5735 i == Xamoeba_5 ? 0 :
5736 i == Xamoeba_6 ? 1 :
5737 i == Xamoeba_7 ? 2 :
5738 i == Xamoeba_8 ? 3 :
5739 i == Xexit_2 ? j + 8 :
5740 i == Xexit_3 ? j + 16 :
5741 i == Xdynamite_1 ? 0 :
5742 i == Xdynamite_2 ? 20 :
5743 i == Xdynamite_3 ? 40 :
5744 i == Xdynamite_4 ? 60 :
5745 i == Xsand_stonein_1 ? j + 1 :
5746 i == Xsand_stonein_2 ? j + 9 :
5747 i == Xsand_stonein_3 ? j + 17 :
5748 i == Xsand_stonein_4 ? j + 25 :
5749 i == Xsand_stoneout_1 && j == 0 ? 0 :
5750 i == Xsand_stoneout_1 && j == 1 ? 0 :
5751 i == Xsand_stoneout_1 && j == 2 ? 1 :
5752 i == Xsand_stoneout_1 && j == 3 ? 2 :
5753 i == Xsand_stoneout_1 && j == 4 ? 2 :
5754 i == Xsand_stoneout_1 && j == 5 ? 3 :
5755 i == Xsand_stoneout_1 && j == 6 ? 4 :
5756 i == Xsand_stoneout_1 && j == 7 ? 4 :
5757 i == Xsand_stoneout_2 && j == 0 ? 5 :
5758 i == Xsand_stoneout_2 && j == 1 ? 6 :
5759 i == Xsand_stoneout_2 && j == 2 ? 7 :
5760 i == Xsand_stoneout_2 && j == 3 ? 8 :
5761 i == Xsand_stoneout_2 && j == 4 ? 9 :
5762 i == Xsand_stoneout_2 && j == 5 ? 11 :
5763 i == Xsand_stoneout_2 && j == 6 ? 13 :
5764 i == Xsand_stoneout_2 && j == 7 ? 15 :
5765 i == Xboom_bug && j == 1 ? 2 :
5766 i == Xboom_bug && j == 2 ? 2 :
5767 i == Xboom_bug && j == 3 ? 4 :
5768 i == Xboom_bug && j == 4 ? 4 :
5769 i == Xboom_bug && j == 5 ? 2 :
5770 i == Xboom_bug && j == 6 ? 2 :
5771 i == Xboom_bug && j == 7 ? 0 :
5772 i == Xboom_bomb && j == 1 ? 2 :
5773 i == Xboom_bomb && j == 2 ? 2 :
5774 i == Xboom_bomb && j == 3 ? 4 :
5775 i == Xboom_bomb && j == 4 ? 4 :
5776 i == Xboom_bomb && j == 5 ? 2 :
5777 i == Xboom_bomb && j == 6 ? 2 :
5778 i == Xboom_bomb && j == 7 ? 0 :
5779 i == Xboom_android && j == 7 ? 6 :
5780 i == Xboom_1 && j == 1 ? 2 :
5781 i == Xboom_1 && j == 2 ? 2 :
5782 i == Xboom_1 && j == 3 ? 4 :
5783 i == Xboom_1 && j == 4 ? 4 :
5784 i == Xboom_1 && j == 5 ? 6 :
5785 i == Xboom_1 && j == 6 ? 6 :
5786 i == Xboom_1 && j == 7 ? 8 :
5787 i == Xboom_2 && j == 0 ? 8 :
5788 i == Xboom_2 && j == 1 ? 8 :
5789 i == Xboom_2 && j == 2 ? 10 :
5790 i == Xboom_2 && j == 3 ? 10 :
5791 i == Xboom_2 && j == 4 ? 10 :
5792 i == Xboom_2 && j == 5 ? 12 :
5793 i == Xboom_2 && j == 6 ? 12 :
5794 i == Xboom_2 && j == 7 ? 12 :
5795 special_animation && j == 4 ? 3 :
5796 effective_action != action ? 0 :
5800 Bitmap *debug_bitmap = g_em->bitmap;
5801 int debug_src_x = g_em->src_x;
5802 int debug_src_y = g_em->src_y;
5805 int frame = getAnimationFrame(g->anim_frames,
5808 g->anim_start_frame,
5811 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y,
5812 g->double_movement && is_backside);
5814 g_em->bitmap = src_bitmap;
5815 g_em->src_x = src_x;
5816 g_em->src_y = src_y;
5817 g_em->src_offset_x = 0;
5818 g_em->src_offset_y = 0;
5819 g_em->dst_offset_x = 0;
5820 g_em->dst_offset_y = 0;
5821 g_em->width = TILEX;
5822 g_em->height = TILEY;
5824 g_em->crumbled_bitmap = NULL;
5825 g_em->crumbled_src_x = 0;
5826 g_em->crumbled_src_y = 0;
5827 g_em->crumbled_border_size = 0;
5829 g_em->has_crumbled_graphics = FALSE;
5830 g_em->preserve_background = FALSE;
5833 if (has_crumbled_graphics && crumbled == IMG_EMPTY_SPACE)
5834 printf("::: empty crumbled: %d [%s], %d, %d\n",
5835 effective_element, element_info[effective_element].token_name,
5836 effective_action, direction);
5839 /* if element can be crumbled, but certain action graphics are just empty
5840 space (like snapping sand with the original R'n'D graphics), do not
5841 treat these empty space graphics as crumbled graphics in EMC engine */
5842 if (has_crumbled_graphics && crumbled != IMG_EMPTY_SPACE)
5844 getGraphicSource(crumbled, frame, &src_bitmap, &src_x, &src_y);
5846 g_em->has_crumbled_graphics = TRUE;
5847 g_em->crumbled_bitmap = src_bitmap;
5848 g_em->crumbled_src_x = src_x;
5849 g_em->crumbled_src_y = src_y;
5850 g_em->crumbled_border_size = graphic_info[crumbled].border_size;
5853 if (!g->double_movement && (effective_action == ACTION_FALLING ||
5854 effective_action == ACTION_MOVING ||
5855 effective_action == ACTION_PUSHING))
5858 (effective_action == ACTION_FALLING ? MV_DOWN : direction);
5859 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? 1 : 0);
5860 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? 1 : 0);
5861 int num_steps = (i == Ydrip_s1 ||
5864 i == Ydrip_s2B ? 16 : 8);
5865 int cx = ABS(dx) * (TILEX / num_steps);
5866 int cy = ABS(dy) * (TILEY / num_steps);
5867 int step_frame = (i == Ydrip_s2 ||
5868 i == Ydrip_s2B ? j + 8 : j) + 1;
5869 int step = (is_backside ? step_frame : num_steps - step_frame);
5871 if (is_backside) /* tile where movement starts */
5873 if (dx < 0 || dy < 0)
5875 g_em->src_offset_x = cx * step;
5876 g_em->src_offset_y = cy * step;
5880 g_em->dst_offset_x = cx * step;
5881 g_em->dst_offset_y = cy * step;
5884 else /* tile where movement ends */
5886 if (dx < 0 || dy < 0)
5888 g_em->dst_offset_x = cx * step;
5889 g_em->dst_offset_y = cy * step;
5893 g_em->src_offset_x = cx * step;
5894 g_em->src_offset_y = cy * step;
5898 g_em->width = TILEX - cx * step;
5899 g_em->height = TILEY - cy * step;
5902 /* create unique graphic identifier to decide if tile must be redrawn */
5903 /* bit 31 - 16 (16 bit): EM style element
5904 bit 15 - 12 ( 4 bit): EM style frame
5905 bit 11 - 6 ( 6 bit): graphic width
5906 bit 5 - 0 ( 6 bit): graphic height */
5907 g_em->unique_identifier =
5908 (i << 16) | (j << 12) | (g_em->width << 6) | g_em->height;
5911 if (g_em->bitmap != debug_bitmap ||
5912 g_em->src_x != debug_src_x ||
5913 g_em->src_y != debug_src_y ||
5914 g_em->src_offset_x != 0 ||
5915 g_em->src_offset_y != 0 ||
5916 g_em->dst_offset_x != 0 ||
5917 g_em->dst_offset_y != 0 ||
5918 g_em->width != TILEX ||
5919 g_em->height != TILEY)
5921 static int last_i = -1;
5929 printf("::: EMC GFX ERROR for element %d -> %d ('%s', '%s', %d)",
5930 i, element, element_info[element].token_name,
5931 element_action_info[effective_action].suffix, direction);
5933 if (element != effective_element)
5934 printf(" [%d ('%s')]",
5936 element_info[effective_element].token_name);
5940 if (g_em->bitmap != debug_bitmap)
5941 printf(" %d (%d): different bitmap! (0x%08x != 0x%08x)\n",
5942 j, is_backside, (int)(g_em->bitmap), (int)(debug_bitmap));
5944 if (g_em->src_x != debug_src_x ||
5945 g_em->src_y != debug_src_y)
5946 printf(" frame %d (%c): %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
5947 j, (is_backside ? 'B' : 'F'),
5948 g_em->src_x, g_em->src_y,
5949 g_em->src_x / 32, g_em->src_y / 32,
5950 debug_src_x, debug_src_y,
5951 debug_src_x / 32, debug_src_y / 32);
5953 if (g_em->src_offset_x != 0 ||
5954 g_em->src_offset_y != 0 ||
5955 g_em->dst_offset_x != 0 ||
5956 g_em->dst_offset_y != 0)
5957 printf(" %d (%d): offsets %d,%d and %d,%d should be all 0\n",
5959 g_em->src_offset_x, g_em->src_offset_y,
5960 g_em->dst_offset_x, g_em->dst_offset_y);
5962 if (g_em->width != TILEX ||
5963 g_em->height != TILEY)
5964 printf(" %d (%d): size %d,%d should be %d,%d\n",
5966 g_em->width, g_em->height, TILEX, TILEY);
5973 for (i = 0; i < TILE_MAX; i++)
5975 for (j = 0; j < 8; j++)
5977 int element = object_mapping[i].element_rnd;
5978 int action = object_mapping[i].action;
5980 if (action == ACTION_SMASHED_BY_ROCK &&
5981 element_info[element].graphic[action] ==
5982 element_info[element].graphic[ACTION_DEFAULT])
5984 /* no separate animation for "smashed by rock" -- use rock instead */
5985 struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
5986 struct GraphicInfo_EM *g_xx = &graphic_info_em_object[Ystone_s][7 - j];
5988 g_em->bitmap = g_xx->bitmap;
5989 g_em->src_x = g_xx->src_x;
5990 g_em->src_y = g_xx->src_y;
5991 g_em->src_offset_x = g_xx->src_offset_x;
5992 g_em->src_offset_y = g_xx->src_offset_y;
5993 g_em->dst_offset_x = g_xx->dst_offset_x;
5994 g_em->dst_offset_y = g_xx->dst_offset_y;
5995 g_em->width = g_xx->width;
5996 g_em->height = g_xx->height;
5998 g_em->preserve_background = TRUE;
6003 for (p = 0; p < 2; p++)
6005 for (i = 0; i < SPR_MAX; i++)
6007 int element = player_mapping[p][i].element_rnd;
6008 int action = player_mapping[p][i].action;
6009 int direction = player_mapping[p][i].direction;
6011 for (j = 0; j < 8; j++)
6013 int effective_element = element;
6014 int effective_action = action;
6015 int graphic = (direction == MV_NONE ?
6016 el_act2img(effective_element, effective_action) :
6017 el_act_dir2img(effective_element, effective_action,
6019 struct GraphicInfo *g = &graphic_info[graphic];
6020 struct GraphicInfo_EM *g_em = &graphic_info_em_player[p][i][7 - j];
6026 Bitmap *debug_bitmap = g_em->bitmap;
6027 int debug_src_x = g_em->src_x;
6028 int debug_src_y = g_em->src_y;
6031 int frame = getAnimationFrame(g->anim_frames,
6034 g->anim_start_frame,
6037 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x,&src_y, FALSE);
6039 g_em->bitmap = src_bitmap;
6040 g_em->src_x = src_x;
6041 g_em->src_y = src_y;
6042 g_em->src_offset_x = 0;
6043 g_em->src_offset_y = 0;
6044 g_em->dst_offset_x = 0;
6045 g_em->dst_offset_y = 0;
6046 g_em->width = TILEX;
6047 g_em->height = TILEY;
6050 if (g_em->bitmap != debug_bitmap ||
6051 g_em->src_x != debug_src_x ||
6052 g_em->src_y != debug_src_y)
6054 static int last_i = -1;
6062 printf("::: EMC GFX ERROR for p/a %d/%d -> %d ('%s', '%s', %d)",
6063 p, i, element, element_info[element].token_name,
6064 element_action_info[effective_action].suffix, direction);
6066 if (element != effective_element)
6067 printf(" [%d ('%s')]",
6069 element_info[effective_element].token_name);
6073 if (g_em->bitmap != debug_bitmap)
6074 printf(" %d: different bitmap! (0x%08x != 0x%08x)\n",
6075 j, (int)(g_em->bitmap), (int)(debug_bitmap));
6077 if (g_em->src_x != debug_src_x ||
6078 g_em->src_y != debug_src_y)
6079 printf(" frame %d: %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
6081 g_em->src_x, g_em->src_y,
6082 g_em->src_x / 32, g_em->src_y / 32,
6083 debug_src_x, debug_src_y,
6084 debug_src_x / 32, debug_src_y / 32);