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)
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->artwork_element, 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_1.width < 0 || door_1.width > DXSIZE)
2454 door_1.width = DXSIZE;
2455 if (door_1.height < 0 || door_1.height > DYSIZE)
2456 door_1.height = DYSIZE;
2457 if (door_2.width < 0 || door_2.width > VXSIZE)
2458 door_2.width = VXSIZE;
2459 if (door_2.height < 0 || door_2.height > VYSIZE)
2460 door_2.height = VYSIZE;
2462 if (door_state == DOOR_GET_STATE)
2463 return(door1 | door2);
2465 if (door_state & DOOR_SET_STATE)
2467 if (door_state & DOOR_ACTION_1)
2468 door1 = door_state & DOOR_ACTION_1;
2469 if (door_state & DOOR_ACTION_2)
2470 door2 = door_state & DOOR_ACTION_2;
2472 return(door1 | door2);
2475 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2476 door_state &= ~DOOR_OPEN_1;
2477 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2478 door_state &= ~DOOR_CLOSE_1;
2479 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2480 door_state &= ~DOOR_OPEN_2;
2481 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2482 door_state &= ~DOOR_CLOSE_2;
2484 door_delay_value = (door_state & DOOR_ACTION_1 ? door_1.step_delay :
2487 if (setup.quick_doors)
2489 stepsize = 20; /* must be choosen to always draw last frame */
2490 door_delay_value = 0;
2493 if (global.autoplay_leveldir)
2495 door_state |= DOOR_NO_DELAY;
2496 door_state &= ~DOOR_CLOSE_ALL;
2499 if (door_state & DOOR_ACTION)
2501 boolean handle_door_1 = (door_state & DOOR_ACTION_1);
2502 boolean handle_door_2 = (door_state & DOOR_ACTION_2);
2503 boolean door_1_done = (!handle_door_1);
2504 boolean door_2_done = (!handle_door_2);
2505 boolean door_1_vertical = (door_1.anim_mode & ANIM_VERTICAL);
2506 boolean door_2_vertical = (door_2.anim_mode & ANIM_VERTICAL);
2507 int door_size_1 = (door_1_vertical ? door_1.height : door_1.width);
2508 int door_size_2 = (door_2_vertical ? door_2.height : door_2.width);
2509 int max_door_size_1 = (door_1_vertical ? DYSIZE : DXSIZE);
2510 int max_door_size_2 = (door_2_vertical ? VYSIZE : VXSIZE);
2511 int door_size = (handle_door_1 ? door_size_1 : door_size_2);
2512 int max_door_size = (handle_door_1 ? max_door_size_1 : max_door_size_2);
2513 int door_skip = max_door_size - door_size;
2515 int end = door_size;
2517 int end = (door_state & DOOR_ACTION_1 &&
2518 door_1.anim_mode & ANIM_VERTICAL ? DYSIZE : DXSIZE);
2521 int start = ((door_state & DOOR_NO_DELAY) ? end : 0);
2523 int start = ((door_state & DOOR_NO_DELAY) ? end : offset_skip);
2527 if (!(door_state & DOOR_NO_DELAY) && !setup.quick_doors)
2529 /* opening door sound has priority over simultaneously closing door */
2530 if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
2531 PlaySoundStereo(SND_DOOR_OPENING, SOUND_MIDDLE);
2532 else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
2533 PlaySoundStereo(SND_DOOR_CLOSING, SOUND_MIDDLE);
2536 for (k = start; k <= end && !(door_1_done && door_2_done); k += stepsize)
2539 Bitmap *bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2540 GC gc = bitmap->stored_clip_gc;
2542 if (door_state & DOOR_ACTION_1)
2544 int a = MIN(x * door_1.step_offset, end);
2545 int p = (door_state & DOOR_OPEN_1 ? end - a : a);
2546 int i = p + door_skip;
2548 if (door_1.anim_mode & ANIM_STATIC_PANEL)
2550 BlitBitmap(bitmap_db_door, drawto,
2551 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1,
2552 DXSIZE, DYSIZE, DX, DY);
2556 BlitBitmap(bitmap_db_door, drawto,
2557 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + p / 2,
2558 DXSIZE, DYSIZE - p / 2, DX, DY);
2560 ClearRectangle(drawto, DX, DY + DYSIZE - p / 2, DXSIZE, p / 2);
2563 if (door_1.anim_mode & ANIM_HORIZONTAL && x <= DXSIZE)
2565 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
2566 int dst1_x = DX + DXSIZE - i, dst1_y = DY;
2567 int src2_x = DXSIZE - i, src2_y = DOOR_GFX_PAGEY1;
2568 int dst2_x = DX, dst2_y = DY;
2569 int width = i, height = DYSIZE;
2571 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2572 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2575 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2576 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2579 else if (door_1.anim_mode & ANIM_VERTICAL && x <= DYSIZE)
2581 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
2582 int dst1_x = DX, dst1_y = DY + DYSIZE - i;
2583 int src2_x = 0, src2_y = DOOR_GFX_PAGEY1 + DYSIZE - i;
2584 int dst2_x = DX, dst2_y = DY;
2585 int width = DXSIZE, height = i;
2587 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2588 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2591 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2592 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2595 else if (x <= DXSIZE) /* ANIM_DEFAULT */
2597 int j = (door_1.anim_mode == ANIM_DEFAULT ? (DXSIZE - i) / 3 : 0);
2599 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2600 BlitBitmapMasked(bitmap, drawto,
2601 DXSIZE, DOOR_GFX_PAGEY1, i, 77,
2602 DX + DXSIZE - i, DY + j);
2603 BlitBitmapMasked(bitmap, drawto,
2604 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
2605 DX + DXSIZE - i, DY + 140 + j);
2606 SetClipOrigin(bitmap, gc, DX - DXSIZE + i,
2607 DY - (DOOR_GFX_PAGEY1 + j));
2608 BlitBitmapMasked(bitmap, drawto,
2609 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
2611 BlitBitmapMasked(bitmap, drawto,
2612 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
2615 BlitBitmapMasked(bitmap, drawto,
2616 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2618 BlitBitmapMasked(bitmap, drawto,
2619 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2621 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2622 BlitBitmapMasked(bitmap, drawto,
2623 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2624 DX + DXSIZE - i, DY + 77 + j);
2625 BlitBitmapMasked(bitmap, drawto,
2626 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2627 DX + DXSIZE - i, DY + 203 + j);
2630 redraw_mask |= REDRAW_DOOR_1;
2631 door_1_done = (a == end);
2634 if (door_state & DOOR_ACTION_2)
2636 int a = MIN(x * door_2.step_offset, door_size_2);
2637 int p = (door_state & DOOR_OPEN_2 ? door_size_2 - a : a);
2638 int i = p + door_skip;
2640 if (door_2.anim_mode & ANIM_STATIC_PANEL)
2642 BlitBitmap(bitmap_db_door, drawto,
2643 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2,
2644 VXSIZE, VYSIZE, VX, VY);
2646 else if (x <= VYSIZE)
2648 BlitBitmap(bitmap_db_door, drawto,
2649 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + p / 2,
2650 VXSIZE, VYSIZE - p / 2, VX, VY);
2652 ClearRectangle(drawto, VX, VY + VYSIZE - p / 2, VXSIZE, p / 2);
2655 if (door_2.anim_mode & ANIM_HORIZONTAL && x <= VXSIZE)
2657 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
2658 int dst1_x = VX + VXSIZE - i, dst1_y = VY;
2659 int src2_x = VXSIZE - i, src2_y = DOOR_GFX_PAGEY2;
2660 int dst2_x = VX, dst2_y = VY;
2661 int width = i, height = VYSIZE;
2663 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2664 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2667 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2668 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2671 else if (door_2.anim_mode & ANIM_VERTICAL && x <= VYSIZE)
2673 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
2674 int dst1_x = VX, dst1_y = VY + VYSIZE - i;
2675 int src2_x = 0, src2_y = DOOR_GFX_PAGEY2 + VYSIZE - i;
2676 int dst2_x = VX, dst2_y = VY;
2677 int width = VXSIZE, height = i;
2679 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2680 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2683 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2684 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2687 else if (x <= VXSIZE) /* ANIM_DEFAULT */
2689 int j = (door_2.anim_mode == ANIM_DEFAULT ? (VXSIZE - i) / 3 : 0);
2691 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2692 BlitBitmapMasked(bitmap, drawto,
2693 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
2694 VX + VXSIZE - i, VY + j);
2695 SetClipOrigin(bitmap, gc,
2696 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2697 BlitBitmapMasked(bitmap, drawto,
2698 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
2701 BlitBitmapMasked(bitmap, drawto,
2702 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2703 i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
2704 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2705 BlitBitmapMasked(bitmap, drawto,
2706 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2708 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2711 redraw_mask |= REDRAW_DOOR_2;
2712 door_2_done = (a == VXSIZE);
2717 if (game_status == GAME_MODE_MAIN)
2720 if (!(door_state & DOOR_NO_DELAY))
2721 WaitUntilDelayReached(&door_delay, door_delay_value);
2725 if (door_state & DOOR_ACTION_1)
2726 door1 = door_state & DOOR_ACTION_1;
2727 if (door_state & DOOR_ACTION_2)
2728 door2 = door_state & DOOR_ACTION_2;
2730 return (door1 | door2);
2733 void DrawSpecialEditorDoor()
2735 /* draw bigger toolbox window */
2736 BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
2737 DOOR_GFX_PAGEX7, 0, EXSIZE + 8, 8,
2739 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2740 EX - 6, VY - 4, EXSIZE + 12, EYSIZE - VYSIZE + 4,
2743 redraw_mask |= REDRAW_ALL;
2746 void UndrawSpecialEditorDoor()
2748 /* draw normal tape recorder window */
2749 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2750 EX - 6, EY - 12, EXSIZE + 12, EYSIZE - VYSIZE + 12,
2753 redraw_mask |= REDRAW_ALL;
2757 /* ---------- new tool button stuff ---------------------------------------- */
2759 /* graphic position values for tool buttons */
2760 #define TOOL_BUTTON_YES_XPOS 2
2761 #define TOOL_BUTTON_YES_YPOS 250
2762 #define TOOL_BUTTON_YES_GFX_YPOS 0
2763 #define TOOL_BUTTON_YES_XSIZE 46
2764 #define TOOL_BUTTON_YES_YSIZE 28
2765 #define TOOL_BUTTON_NO_XPOS 52
2766 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2767 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2768 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2769 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2770 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2771 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2772 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2773 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2774 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2775 #define TOOL_BUTTON_PLAYER_XSIZE 30
2776 #define TOOL_BUTTON_PLAYER_YSIZE 30
2777 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2778 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2779 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2780 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2781 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2782 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2783 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2784 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2785 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2786 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2787 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2788 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2789 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2790 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2791 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2792 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2793 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2794 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2795 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2796 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2805 } toolbutton_info[NUM_TOOL_BUTTONS] =
2808 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2809 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2810 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2815 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2816 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2817 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2822 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2823 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2824 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2825 TOOL_CTRL_ID_CONFIRM,
2829 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2830 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2831 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2832 TOOL_CTRL_ID_PLAYER_1,
2836 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2837 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2838 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2839 TOOL_CTRL_ID_PLAYER_2,
2843 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2844 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2845 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2846 TOOL_CTRL_ID_PLAYER_3,
2850 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2851 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2852 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2853 TOOL_CTRL_ID_PLAYER_4,
2858 void CreateToolButtons()
2862 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2864 Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2865 Bitmap *deco_bitmap = None;
2866 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2867 struct GadgetInfo *gi;
2868 unsigned long event_mask;
2869 int gd_xoffset, gd_yoffset;
2870 int gd_x1, gd_x2, gd_y;
2873 event_mask = GD_EVENT_RELEASED;
2875 gd_xoffset = toolbutton_info[i].xpos;
2876 gd_yoffset = toolbutton_info[i].ypos;
2877 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2878 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2879 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2881 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2883 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
2885 getMiniGraphicSource(PLAYER_NR_GFX(IMG_PLAYER_1, player_nr),
2886 &deco_bitmap, &deco_x, &deco_y);
2887 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2888 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2891 gi = CreateGadget(GDI_CUSTOM_ID, id,
2892 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2893 GDI_X, DX + toolbutton_info[i].x,
2894 GDI_Y, DY + toolbutton_info[i].y,
2895 GDI_WIDTH, toolbutton_info[i].width,
2896 GDI_HEIGHT, toolbutton_info[i].height,
2897 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2898 GDI_STATE, GD_BUTTON_UNPRESSED,
2899 GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
2900 GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
2901 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
2902 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2903 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2904 GDI_DECORATION_SHIFTING, 1, 1,
2905 GDI_EVENT_MASK, event_mask,
2906 GDI_CALLBACK_ACTION, HandleToolButtons,
2910 Error(ERR_EXIT, "cannot create gadget");
2912 tool_gadget[id] = gi;
2916 void FreeToolButtons()
2920 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2921 FreeGadget(tool_gadget[i]);
2924 static void UnmapToolButtons()
2928 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2929 UnmapGadget(tool_gadget[i]);
2932 static void HandleToolButtons(struct GadgetInfo *gi)
2934 request_gadget_id = gi->custom_id;
2937 static struct Mapping_EM_to_RND_object
2940 boolean is_rnd_to_em_mapping; /* unique mapping EM <-> RND */
2941 boolean is_backside; /* backside of moving element */
2947 em_object_mapping_list[] =
2950 Xblank, TRUE, FALSE,
2954 Yacid_splash_eB, FALSE, FALSE,
2955 EL_ACID_SPLASH_RIGHT, -1, -1
2958 Yacid_splash_wB, FALSE, FALSE,
2959 EL_ACID_SPLASH_LEFT, -1, -1
2962 #ifdef EM_ENGINE_BAD_ROLL
2964 Xstone_force_e, FALSE, FALSE,
2965 EL_ROCK, -1, MV_BIT_RIGHT
2968 Xstone_force_w, FALSE, FALSE,
2969 EL_ROCK, -1, MV_BIT_LEFT
2972 Xnut_force_e, FALSE, FALSE,
2973 EL_NUT, -1, MV_BIT_RIGHT
2976 Xnut_force_w, FALSE, FALSE,
2977 EL_NUT, -1, MV_BIT_LEFT
2980 Xspring_force_e, FALSE, FALSE,
2981 EL_SPRING, -1, MV_BIT_RIGHT
2984 Xspring_force_w, FALSE, FALSE,
2985 EL_SPRING, -1, MV_BIT_LEFT
2988 Xemerald_force_e, FALSE, FALSE,
2989 EL_EMERALD, -1, MV_BIT_RIGHT
2992 Xemerald_force_w, FALSE, FALSE,
2993 EL_EMERALD, -1, MV_BIT_LEFT
2996 Xdiamond_force_e, FALSE, FALSE,
2997 EL_DIAMOND, -1, MV_BIT_RIGHT
3000 Xdiamond_force_w, FALSE, FALSE,
3001 EL_DIAMOND, -1, MV_BIT_LEFT
3004 Xbomb_force_e, FALSE, FALSE,
3005 EL_BOMB, -1, MV_BIT_RIGHT
3008 Xbomb_force_w, FALSE, FALSE,
3009 EL_BOMB, -1, MV_BIT_LEFT
3011 #endif /* EM_ENGINE_BAD_ROLL */
3014 Xstone, TRUE, FALSE,
3018 Xstone_pause, FALSE, FALSE,
3022 Xstone_fall, FALSE, FALSE,
3026 Ystone_s, FALSE, FALSE,
3027 EL_ROCK, ACTION_FALLING, -1
3030 Ystone_sB, FALSE, TRUE,
3031 EL_ROCK, ACTION_FALLING, -1
3034 Ystone_e, FALSE, FALSE,
3035 EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT
3038 Ystone_eB, FALSE, TRUE,
3039 EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT
3042 Ystone_w, FALSE, FALSE,
3043 EL_ROCK, ACTION_MOVING, MV_BIT_LEFT
3046 Ystone_wB, FALSE, TRUE,
3047 EL_ROCK, ACTION_MOVING, MV_BIT_LEFT
3054 Xnut_pause, FALSE, FALSE,
3058 Xnut_fall, FALSE, FALSE,
3062 Ynut_s, FALSE, FALSE,
3063 EL_NUT, ACTION_FALLING, -1
3066 Ynut_sB, FALSE, TRUE,
3067 EL_NUT, ACTION_FALLING, -1
3070 Ynut_e, FALSE, FALSE,
3071 EL_NUT, ACTION_MOVING, MV_BIT_RIGHT
3074 Ynut_eB, FALSE, TRUE,
3075 EL_NUT, ACTION_MOVING, MV_BIT_RIGHT
3078 Ynut_w, FALSE, FALSE,
3079 EL_NUT, ACTION_MOVING, MV_BIT_LEFT
3082 Ynut_wB, FALSE, TRUE,
3083 EL_NUT, ACTION_MOVING, MV_BIT_LEFT
3086 Xbug_n, TRUE, FALSE,
3090 Xbug_e, TRUE, FALSE,
3091 EL_BUG_RIGHT, -1, -1
3094 Xbug_s, TRUE, FALSE,
3098 Xbug_w, TRUE, FALSE,
3102 Xbug_gon, FALSE, FALSE,
3106 Xbug_goe, FALSE, FALSE,
3107 EL_BUG_RIGHT, -1, -1
3110 Xbug_gos, FALSE, FALSE,
3114 Xbug_gow, FALSE, FALSE,
3118 Ybug_n, FALSE, FALSE,
3119 EL_BUG, ACTION_MOVING, MV_BIT_UP
3122 Ybug_nB, FALSE, TRUE,
3123 EL_BUG, ACTION_MOVING, MV_BIT_UP
3126 Ybug_e, FALSE, FALSE,
3127 EL_BUG, ACTION_MOVING, MV_BIT_RIGHT
3130 Ybug_eB, FALSE, TRUE,
3131 EL_BUG, ACTION_MOVING, MV_BIT_RIGHT
3134 Ybug_s, FALSE, FALSE,
3135 EL_BUG, ACTION_MOVING, MV_BIT_DOWN
3138 Ybug_sB, FALSE, TRUE,
3139 EL_BUG, ACTION_MOVING, MV_BIT_DOWN
3142 Ybug_w, FALSE, FALSE,
3143 EL_BUG, ACTION_MOVING, MV_BIT_LEFT
3146 Ybug_wB, FALSE, TRUE,
3147 EL_BUG, ACTION_MOVING, MV_BIT_LEFT
3150 Ybug_w_n, FALSE, FALSE,
3151 EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_UP
3154 Ybug_n_e, FALSE, FALSE,
3155 EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3158 Ybug_e_s, FALSE, FALSE,
3159 EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
3162 Ybug_s_w, FALSE, FALSE,
3163 EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3166 Ybug_e_n, FALSE, FALSE,
3167 EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
3170 Ybug_s_e, FALSE, FALSE,
3171 EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3174 Ybug_w_s, FALSE, FALSE,
3175 EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
3178 Ybug_n_w, FALSE, FALSE,
3179 EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3182 Ybug_stone, FALSE, FALSE,
3183 EL_BUG, ACTION_SMASHED_BY_ROCK, -1
3186 Ybug_spring, FALSE, FALSE,
3187 EL_BUG, ACTION_SMASHED_BY_SPRING, -1
3190 Xtank_n, TRUE, FALSE,
3191 EL_SPACESHIP_UP, -1, -1
3194 Xtank_e, TRUE, FALSE,
3195 EL_SPACESHIP_RIGHT, -1, -1
3198 Xtank_s, TRUE, FALSE,
3199 EL_SPACESHIP_DOWN, -1, -1
3202 Xtank_w, TRUE, FALSE,
3203 EL_SPACESHIP_LEFT, -1, -1
3206 Xtank_gon, FALSE, FALSE,
3207 EL_SPACESHIP_UP, -1, -1
3210 Xtank_goe, FALSE, FALSE,
3211 EL_SPACESHIP_RIGHT, -1, -1
3214 Xtank_gos, FALSE, FALSE,
3215 EL_SPACESHIP_DOWN, -1, -1
3218 Xtank_gow, FALSE, FALSE,
3219 EL_SPACESHIP_LEFT, -1, -1
3222 Ytank_n, FALSE, FALSE,
3223 EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP
3226 Ytank_nB, FALSE, TRUE,
3227 EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP
3230 Ytank_e, FALSE, FALSE,
3231 EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT
3234 Ytank_eB, FALSE, TRUE,
3235 EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT
3238 Ytank_s, FALSE, FALSE,
3239 EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN
3242 Ytank_sB, FALSE, TRUE,
3243 EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN
3246 Ytank_w, FALSE, FALSE,
3247 EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT
3250 Ytank_wB, FALSE, TRUE,
3251 EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT
3254 Ytank_w_n, FALSE, FALSE,
3255 EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_UP
3258 Ytank_n_e, FALSE, FALSE,
3259 EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3262 Ytank_e_s, FALSE, FALSE,
3263 EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
3266 Ytank_s_w, FALSE, FALSE,
3267 EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3270 Ytank_e_n, FALSE, FALSE,
3271 EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
3274 Ytank_s_e, FALSE, FALSE,
3275 EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3278 Ytank_w_s, FALSE, FALSE,
3279 EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
3282 Ytank_n_w, FALSE, FALSE,
3283 EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3286 Ytank_stone, FALSE, FALSE,
3287 EL_SPACESHIP, ACTION_SMASHED_BY_ROCK, -1
3290 Ytank_spring, FALSE, FALSE,
3291 EL_SPACESHIP, ACTION_SMASHED_BY_SPRING, -1
3294 Xandroid, TRUE, FALSE,
3295 EL_EMC_ANDROID, ACTION_ACTIVE, -1
3298 Xandroid_1_n, FALSE, FALSE,
3299 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_UP
3302 Xandroid_2_n, FALSE, FALSE,
3303 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_UP
3306 Xandroid_1_e, FALSE, FALSE,
3307 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_RIGHT
3310 Xandroid_2_e, FALSE, FALSE,
3311 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_RIGHT
3314 Xandroid_1_w, FALSE, FALSE,
3315 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_LEFT
3318 Xandroid_2_w, FALSE, FALSE,
3319 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_LEFT
3322 Xandroid_1_s, FALSE, FALSE,
3323 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_DOWN
3326 Xandroid_2_s, FALSE, FALSE,
3327 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_DOWN
3330 Yandroid_n, FALSE, FALSE,
3331 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_UP
3334 Yandroid_nB, FALSE, TRUE,
3335 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_UP
3338 Yandroid_ne, FALSE, FALSE,
3339 EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_UPRIGHT
3342 Yandroid_neB, FALSE, TRUE,
3343 EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_UPRIGHT
3346 Yandroid_e, FALSE, FALSE,
3347 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_RIGHT
3350 Yandroid_eB, FALSE, TRUE,
3351 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_RIGHT
3354 Yandroid_se, FALSE, FALSE,
3355 EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_DOWNRIGHT
3358 Yandroid_seB, FALSE, TRUE,
3359 EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_DOWNRIGHT
3362 Yandroid_s, FALSE, FALSE,
3363 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_DOWN
3366 Yandroid_sB, FALSE, TRUE,
3367 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_DOWN
3370 Yandroid_sw, FALSE, FALSE,
3371 EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_DOWNLEFT
3374 Yandroid_swB, FALSE, TRUE,
3375 EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_DOWNLEFT
3378 Yandroid_w, FALSE, FALSE,
3379 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_LEFT
3382 Yandroid_wB, FALSE, TRUE,
3383 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_LEFT
3386 Yandroid_nw, FALSE, FALSE,
3387 EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_UPLEFT
3390 Yandroid_nwB, FALSE, TRUE,
3391 EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_UPLEFT
3394 Xspring, TRUE, FALSE,
3398 Xspring_pause, FALSE, FALSE,
3402 Xspring_e, FALSE, FALSE,
3406 Xspring_w, FALSE, FALSE,
3410 Xspring_fall, FALSE, FALSE,
3414 Yspring_s, FALSE, FALSE,
3415 EL_SPRING, ACTION_FALLING, -1
3418 Yspring_sB, FALSE, TRUE,
3419 EL_SPRING, ACTION_FALLING, -1
3422 Yspring_e, FALSE, FALSE,
3423 EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT
3426 Yspring_eB, FALSE, TRUE,
3427 EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT
3430 Yspring_w, FALSE, FALSE,
3431 EL_SPRING, ACTION_MOVING, MV_BIT_LEFT
3434 Yspring_wB, FALSE, TRUE,
3435 EL_SPRING, ACTION_MOVING, MV_BIT_LEFT
3438 Yspring_kill_e, FALSE, FALSE,
3439 EL_ROBOT, ACTION_SLURPED_BY_SPRING, MV_BIT_RIGHT
3442 Yspring_kill_eB, FALSE, TRUE,
3443 EL_ROBOT, ACTION_SLURPED_BY_SPRING, MV_BIT_RIGHT
3446 Yspring_kill_w, FALSE, FALSE,
3447 EL_ROBOT, ACTION_SLURPED_BY_SPRING, MV_BIT_LEFT
3450 Yspring_kill_wB, FALSE, TRUE,
3451 EL_ROBOT, ACTION_SLURPED_BY_SPRING, MV_BIT_LEFT
3454 Xeater_n, TRUE, FALSE,
3458 Xeater_e, FALSE, FALSE,
3462 Xeater_w, FALSE, FALSE,
3466 Xeater_s, FALSE, FALSE,
3470 Yeater_n, FALSE, FALSE,
3471 EL_YAMYAM, ACTION_MOVING, MV_BIT_UP
3474 Yeater_nB, FALSE, TRUE,
3475 EL_YAMYAM, ACTION_MOVING, MV_BIT_UP
3478 Yeater_e, FALSE, FALSE,
3479 EL_YAMYAM, ACTION_MOVING, MV_BIT_RIGHT
3482 Yeater_eB, FALSE, TRUE,
3483 EL_YAMYAM, ACTION_MOVING, MV_BIT_RIGHT
3486 Yeater_s, FALSE, FALSE,
3487 EL_YAMYAM, ACTION_MOVING, MV_BIT_DOWN
3490 Yeater_sB, FALSE, TRUE,
3491 EL_YAMYAM, ACTION_MOVING, MV_BIT_DOWN
3494 Yeater_w, FALSE, FALSE,
3495 EL_YAMYAM, ACTION_MOVING, MV_BIT_LEFT
3498 Yeater_wB, FALSE, TRUE,
3499 EL_YAMYAM, ACTION_MOVING, MV_BIT_LEFT
3502 Yeater_stone, FALSE, FALSE,
3503 EL_YAMYAM, ACTION_SMASHED_BY_ROCK, -1
3506 Yeater_spring, FALSE, FALSE,
3507 EL_YAMYAM, ACTION_SMASHED_BY_SPRING, -1
3510 Xalien, TRUE, FALSE,
3514 Xalien_pause, FALSE, FALSE,
3518 Yalien_n, FALSE, FALSE,
3519 EL_ROBOT, ACTION_MOVING, MV_BIT_UP
3522 Yalien_nB, FALSE, TRUE,
3523 EL_ROBOT, ACTION_MOVING, MV_BIT_UP
3526 Yalien_e, FALSE, FALSE,
3527 EL_ROBOT, ACTION_MOVING, MV_BIT_RIGHT
3530 Yalien_eB, FALSE, TRUE,
3531 EL_ROBOT, ACTION_MOVING, MV_BIT_RIGHT
3534 Yalien_s, FALSE, FALSE,
3535 EL_ROBOT, ACTION_MOVING, MV_BIT_DOWN
3538 Yalien_sB, FALSE, TRUE,
3539 EL_ROBOT, ACTION_MOVING, MV_BIT_DOWN
3542 Yalien_w, FALSE, FALSE,
3543 EL_ROBOT, ACTION_MOVING, MV_BIT_LEFT
3546 Yalien_wB, FALSE, TRUE,
3547 EL_ROBOT, ACTION_MOVING, MV_BIT_LEFT
3550 Yalien_stone, FALSE, FALSE,
3551 EL_ROBOT, ACTION_SMASHED_BY_ROCK, -1
3554 Yalien_spring, FALSE, FALSE,
3555 EL_ROBOT, ACTION_SMASHED_BY_SPRING, -1
3558 Xemerald, TRUE, FALSE,
3562 Xemerald_pause, FALSE, FALSE,
3566 Xemerald_fall, FALSE, FALSE,
3570 Xemerald_shine, FALSE, FALSE,
3571 EL_EMERALD, ACTION_TWINKLING, -1
3574 Yemerald_s, FALSE, FALSE,
3575 EL_EMERALD, ACTION_FALLING, -1
3578 Yemerald_sB, FALSE, TRUE,
3579 EL_EMERALD, ACTION_FALLING, -1
3582 Yemerald_e, FALSE, FALSE,
3583 EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT
3586 Yemerald_eB, FALSE, TRUE,
3587 EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT
3590 Yemerald_w, FALSE, FALSE,
3591 EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT
3594 Yemerald_wB, FALSE, TRUE,
3595 EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT
3598 Yemerald_eat, FALSE, FALSE,
3599 EL_EMERALD, ACTION_COLLECTING, -1
3602 Yemerald_stone, FALSE, FALSE,
3603 EL_NUT, ACTION_BREAKING, -1
3606 Xdiamond, TRUE, FALSE,
3610 Xdiamond_pause, FALSE, FALSE,
3614 Xdiamond_fall, FALSE, FALSE,
3618 Xdiamond_shine, FALSE, FALSE,
3619 EL_DIAMOND, ACTION_TWINKLING, -1
3622 Ydiamond_s, FALSE, FALSE,
3623 EL_DIAMOND, ACTION_FALLING, -1
3626 Ydiamond_sB, FALSE, TRUE,
3627 EL_DIAMOND, ACTION_FALLING, -1
3630 Ydiamond_e, FALSE, FALSE,
3631 EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT
3634 Ydiamond_eB, FALSE, TRUE,
3635 EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT
3638 Ydiamond_w, FALSE, FALSE,
3639 EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT
3642 Ydiamond_wB, FALSE, TRUE,
3643 EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT
3646 Ydiamond_eat, FALSE, FALSE,
3647 EL_DIAMOND, ACTION_COLLECTING, -1
3650 Ydiamond_stone, FALSE, FALSE,
3651 EL_DIAMOND, ACTION_SMASHED_BY_ROCK, -1
3654 Xdrip_fall, TRUE, FALSE,
3655 EL_AMOEBA_DROP, -1, -1
3658 Xdrip_stretch, FALSE, FALSE,
3659 EL_AMOEBA_DROP, ACTION_FALLING, -1
3662 Xdrip_stretchB, FALSE, TRUE,
3663 EL_AMOEBA_DROP, ACTION_FALLING, -1
3666 Xdrip_eat, FALSE, FALSE,
3667 EL_AMOEBA_DROP, ACTION_GROWING, -1
3670 Ydrip_s1, FALSE, FALSE,
3671 EL_AMOEBA_DROP, ACTION_FALLING, -1
3674 Ydrip_s1B, FALSE, TRUE,
3675 EL_AMOEBA_DROP, ACTION_FALLING, -1
3678 Ydrip_s2, FALSE, FALSE,
3679 EL_AMOEBA_DROP, ACTION_FALLING, -1
3682 Ydrip_s2B, FALSE, TRUE,
3683 EL_AMOEBA_DROP, ACTION_FALLING, -1
3690 Xbomb_pause, FALSE, FALSE,
3694 Xbomb_fall, FALSE, FALSE,
3698 Ybomb_s, FALSE, FALSE,
3699 EL_BOMB, ACTION_FALLING, -1
3702 Ybomb_sB, FALSE, TRUE,
3703 EL_BOMB, ACTION_FALLING, -1
3706 Ybomb_e, FALSE, FALSE,
3707 EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT
3710 Ybomb_eB, FALSE, TRUE,
3711 EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT
3714 Ybomb_w, FALSE, FALSE,
3715 EL_BOMB, ACTION_MOVING, MV_BIT_LEFT
3718 Ybomb_wB, FALSE, TRUE,
3719 EL_BOMB, ACTION_MOVING, MV_BIT_LEFT
3722 Ybomb_eat, FALSE, FALSE,
3723 EL_BOMB, ACTION_ACTIVATING, -1
3726 Xballoon, TRUE, FALSE,
3730 Yballoon_n, FALSE, FALSE,
3731 EL_BALLOON, ACTION_MOVING, MV_BIT_UP
3734 Yballoon_nB, FALSE, TRUE,
3735 EL_BALLOON, ACTION_MOVING, MV_BIT_UP
3738 Yballoon_e, FALSE, FALSE,
3739 EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT
3742 Yballoon_eB, FALSE, TRUE,
3743 EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT
3746 Yballoon_s, FALSE, FALSE,
3747 EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN
3750 Yballoon_sB, FALSE, TRUE,
3751 EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN
3754 Yballoon_w, FALSE, FALSE,
3755 EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT
3758 Yballoon_wB, FALSE, TRUE,
3759 EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT
3762 Xgrass, TRUE, FALSE,
3763 EL_EMC_GRASS, -1, -1
3766 Ygrass_nB, FALSE, FALSE,
3767 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_UP
3770 Ygrass_eB, FALSE, FALSE,
3771 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_RIGHT
3774 Ygrass_sB, FALSE, FALSE,
3775 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_DOWN
3778 Ygrass_wB, FALSE, FALSE,
3779 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_LEFT
3786 Ydirt_nB, FALSE, FALSE,
3787 EL_SAND, ACTION_DIGGING, MV_BIT_UP
3790 Ydirt_eB, FALSE, FALSE,
3791 EL_SAND, ACTION_DIGGING, MV_BIT_RIGHT
3794 Ydirt_sB, FALSE, FALSE,
3795 EL_SAND, ACTION_DIGGING, MV_BIT_DOWN
3798 Ydirt_wB, FALSE, FALSE,
3799 EL_SAND, ACTION_DIGGING, MV_BIT_LEFT
3802 Xacid_ne, TRUE, FALSE,
3803 EL_ACID_POOL_TOPRIGHT, -1, -1
3806 Xacid_se, TRUE, FALSE,
3807 EL_ACID_POOL_BOTTOMRIGHT, -1, -1
3810 Xacid_s, TRUE, FALSE,
3811 EL_ACID_POOL_BOTTOM, -1, -1
3814 Xacid_sw, TRUE, FALSE,
3815 EL_ACID_POOL_BOTTOMLEFT, -1, -1
3818 Xacid_nw, TRUE, FALSE,
3819 EL_ACID_POOL_TOPLEFT, -1, -1
3822 Xacid_1, TRUE, FALSE,
3826 Xacid_2, FALSE, FALSE,
3830 Xacid_3, FALSE, FALSE,
3834 Xacid_4, FALSE, FALSE,
3838 Xacid_5, FALSE, FALSE,
3842 Xacid_6, FALSE, FALSE,
3846 Xacid_7, FALSE, FALSE,
3850 Xacid_8, FALSE, FALSE,
3854 Xball_1, TRUE, FALSE,
3855 EL_EMC_MAGIC_BALL, -1, -1
3858 Xball_1B, FALSE, FALSE,
3859 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
3862 Xball_2, FALSE, FALSE,
3863 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
3866 Xball_2B, FALSE, FALSE,
3867 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
3870 Yball_eat, FALSE, FALSE,
3871 EL_EMC_MAGIC_BALL, ACTION_DROPPING, -1
3874 Ykey_1_eat, FALSE, FALSE,
3875 EL_EM_KEY_1, ACTION_COLLECTING, -1
3878 Ykey_2_eat, FALSE, FALSE,
3879 EL_EM_KEY_2, ACTION_COLLECTING, -1
3882 Ykey_3_eat, FALSE, FALSE,
3883 EL_EM_KEY_3, ACTION_COLLECTING, -1
3886 Ykey_4_eat, FALSE, FALSE,
3887 EL_EM_KEY_4, ACTION_COLLECTING, -1
3890 Ykey_5_eat, FALSE, FALSE,
3891 EL_EMC_KEY_5, ACTION_COLLECTING, -1
3894 Ykey_6_eat, FALSE, FALSE,
3895 EL_EMC_KEY_6, ACTION_COLLECTING, -1
3898 Ykey_7_eat, FALSE, FALSE,
3899 EL_EMC_KEY_7, ACTION_COLLECTING, -1
3902 Ykey_8_eat, FALSE, FALSE,
3903 EL_EMC_KEY_8, ACTION_COLLECTING, -1
3906 Ylenses_eat, FALSE, FALSE,
3907 EL_EMC_LENSES, ACTION_COLLECTING, -1
3910 Ymagnify_eat, FALSE, FALSE,
3911 EL_EMC_MAGNIFIER, ACTION_COLLECTING, -1
3914 Ygrass_eat, FALSE, FALSE,
3915 EL_EMC_GRASS, ACTION_SNAPPING, -1
3918 Ydirt_eat, FALSE, FALSE,
3919 EL_SAND, ACTION_SNAPPING, -1
3922 Xgrow_ns, TRUE, FALSE,
3923 EL_EXPANDABLE_WALL_VERTICAL, -1, -1
3926 Ygrow_ns_eat, FALSE, FALSE,
3927 EL_EXPANDABLE_WALL_VERTICAL, ACTION_GROWING, -1
3930 Xgrow_ew, TRUE, FALSE,
3931 EL_EXPANDABLE_WALL_HORIZONTAL, -1, -1
3934 Ygrow_ew_eat, FALSE, FALSE,
3935 EL_EXPANDABLE_WALL_HORIZONTAL, ACTION_GROWING, -1
3938 Xwonderwall, TRUE, FALSE,
3939 EL_MAGIC_WALL, -1, -1
3942 XwonderwallB, FALSE, FALSE,
3943 EL_MAGIC_WALL, ACTION_ACTIVE, -1
3946 Xamoeba_1, TRUE, FALSE,
3947 EL_AMOEBA_DRY, ACTION_OTHER, -1
3950 Xamoeba_2, FALSE, FALSE,
3951 EL_AMOEBA_DRY, ACTION_OTHER, -1
3954 Xamoeba_3, FALSE, FALSE,
3955 EL_AMOEBA_DRY, ACTION_OTHER, -1
3958 Xamoeba_4, FALSE, FALSE,
3959 EL_AMOEBA_DRY, ACTION_OTHER, -1
3962 Xamoeba_5, TRUE, FALSE,
3963 EL_AMOEBA_WET, ACTION_OTHER, -1
3966 Xamoeba_6, FALSE, FALSE,
3967 EL_AMOEBA_WET, ACTION_OTHER, -1
3970 Xamoeba_7, FALSE, FALSE,
3971 EL_AMOEBA_WET, ACTION_OTHER, -1
3974 Xamoeba_8, FALSE, FALSE,
3975 EL_AMOEBA_WET, ACTION_OTHER, -1
3978 Xdoor_1, TRUE, FALSE,
3979 EL_EM_GATE_1, -1, -1
3982 Xdoor_2, TRUE, FALSE,
3983 EL_EM_GATE_2, -1, -1
3986 Xdoor_3, TRUE, FALSE,
3987 EL_EM_GATE_3, -1, -1
3990 Xdoor_4, TRUE, FALSE,
3991 EL_EM_GATE_4, -1, -1
3994 Xdoor_5, TRUE, FALSE,
3995 EL_EMC_GATE_5, -1, -1
3998 Xdoor_6, TRUE, FALSE,
3999 EL_EMC_GATE_6, -1, -1
4002 Xdoor_7, TRUE, FALSE,
4003 EL_EMC_GATE_7, -1, -1
4006 Xdoor_8, TRUE, FALSE,
4007 EL_EMC_GATE_8, -1, -1
4010 Xkey_1, TRUE, FALSE,
4014 Xkey_2, TRUE, FALSE,
4018 Xkey_3, TRUE, FALSE,
4022 Xkey_4, TRUE, FALSE,
4026 Xkey_5, TRUE, FALSE,
4027 EL_EMC_KEY_5, -1, -1
4030 Xkey_6, TRUE, FALSE,
4031 EL_EMC_KEY_6, -1, -1
4034 Xkey_7, TRUE, FALSE,
4035 EL_EMC_KEY_7, -1, -1
4038 Xkey_8, TRUE, FALSE,
4039 EL_EMC_KEY_8, -1, -1
4042 Xwind_n, TRUE, FALSE,
4043 EL_BALLOON_SWITCH_UP, -1, -1
4046 Xwind_e, TRUE, FALSE,
4047 EL_BALLOON_SWITCH_RIGHT, -1, -1
4050 Xwind_s, TRUE, FALSE,
4051 EL_BALLOON_SWITCH_DOWN, -1, -1
4054 Xwind_w, TRUE, FALSE,
4055 EL_BALLOON_SWITCH_LEFT, -1, -1
4058 Xwind_nesw, TRUE, FALSE,
4059 EL_BALLOON_SWITCH_ANY, -1, -1
4062 Xwind_stop, TRUE, FALSE,
4063 EL_BALLOON_SWITCH_NONE, -1, -1
4067 EL_EXIT_CLOSED, -1, -1
4070 Xexit_1, TRUE, FALSE,
4071 EL_EXIT_OPEN, -1, -1
4074 Xexit_2, FALSE, FALSE,
4075 EL_EXIT_OPEN, -1, -1
4078 Xexit_3, FALSE, FALSE,
4079 EL_EXIT_OPEN, -1, -1
4082 Xdynamite, TRUE, FALSE,
4086 Ydynamite_eat, FALSE, FALSE,
4087 EL_DYNAMITE, ACTION_COLLECTING, -1
4090 Xdynamite_1, TRUE, FALSE,
4091 EL_DYNAMITE_ACTIVE, -1, -1
4094 Xdynamite_2, FALSE, FALSE,
4095 EL_DYNAMITE_ACTIVE, -1, -1
4098 Xdynamite_3, FALSE, FALSE,
4099 EL_DYNAMITE_ACTIVE, -1, -1
4102 Xdynamite_4, FALSE, FALSE,
4103 EL_DYNAMITE_ACTIVE, -1, -1
4106 Xbumper, TRUE, FALSE,
4107 EL_EMC_SPRING_BUMPER, -1, -1
4110 XbumperB, FALSE, FALSE,
4111 EL_EMC_SPRING_BUMPER, ACTION_ACTIVE, -1
4114 Xwheel, TRUE, FALSE,
4115 EL_ROBOT_WHEEL, -1, -1
4118 XwheelB, FALSE, FALSE,
4119 EL_ROBOT_WHEEL, ACTION_ACTIVE, -1
4122 Xswitch, TRUE, FALSE,
4123 EL_EMC_MAGIC_BALL_SWITCH, -1, -1
4126 XswitchB, FALSE, FALSE,
4127 EL_EMC_MAGIC_BALL_SWITCH, ACTION_ACTIVE, -1
4131 EL_QUICKSAND_EMPTY, -1, -1
4134 Xsand_stone, TRUE, FALSE,
4135 EL_QUICKSAND_FULL, -1, -1
4138 Xsand_stonein_1, FALSE, FALSE,
4139 EL_ROCK, ACTION_FILLING, -1
4142 Xsand_stonein_2, FALSE, FALSE,
4143 EL_ROCK, ACTION_FILLING, -1
4146 Xsand_stonein_3, FALSE, FALSE,
4147 EL_ROCK, ACTION_FILLING, -1
4150 Xsand_stonein_4, FALSE, FALSE,
4151 EL_ROCK, ACTION_FILLING, -1
4154 Xsand_stonesand_1, FALSE, FALSE,
4155 EL_QUICKSAND_FULL, -1, -1
4158 Xsand_stonesand_2, FALSE, FALSE,
4159 EL_QUICKSAND_FULL, -1, -1
4162 Xsand_stonesand_3, FALSE, FALSE,
4163 EL_QUICKSAND_FULL, -1, -1
4166 Xsand_stonesand_4, FALSE, FALSE,
4167 EL_QUICKSAND_FULL, -1, -1
4170 Xsand_stoneout_1, FALSE, FALSE,
4171 EL_ROCK, ACTION_EMPTYING, -1
4174 Xsand_stoneout_2, FALSE, FALSE,
4175 EL_ROCK, ACTION_EMPTYING, -1
4178 Xsand_sandstone_1, FALSE, FALSE,
4179 EL_QUICKSAND_FULL, -1, -1
4182 Xsand_sandstone_2, FALSE, FALSE,
4183 EL_QUICKSAND_FULL, -1, -1
4186 Xsand_sandstone_3, FALSE, FALSE,
4187 EL_QUICKSAND_FULL, -1, -1
4190 Xsand_sandstone_4, FALSE, FALSE,
4191 EL_QUICKSAND_FULL, -1, -1
4194 Xplant, TRUE, FALSE,
4195 EL_EMC_PLANT, -1, -1
4198 Yplant, FALSE, FALSE,
4199 EL_EMC_PLANT, -1, -1
4202 Xlenses, TRUE, FALSE,
4203 EL_EMC_LENSES, -1, -1
4206 Xmagnify, TRUE, FALSE,
4207 EL_EMC_MAGNIFIER, -1, -1
4210 Xdripper, TRUE, FALSE,
4211 EL_EMC_DRIPPER, -1, -1
4214 XdripperB, FALSE, FALSE,
4215 EL_EMC_DRIPPER, ACTION_ACTIVE, -1
4218 Xfake_blank, TRUE, FALSE,
4219 EL_INVISIBLE_WALL, -1, -1
4222 Xfake_blankB, FALSE, FALSE,
4223 EL_INVISIBLE_WALL, ACTION_ACTIVE, -1
4226 Xfake_grass, TRUE, FALSE,
4227 EL_EMC_FAKE_GRASS, -1, -1
4230 Xfake_grassB, FALSE, FALSE,
4231 EL_EMC_FAKE_GRASS, ACTION_ACTIVE, -1
4234 Xfake_door_1, TRUE, FALSE,
4235 EL_EM_GATE_1_GRAY, -1, -1
4238 Xfake_door_2, TRUE, FALSE,
4239 EL_EM_GATE_2_GRAY, -1, -1
4242 Xfake_door_3, TRUE, FALSE,
4243 EL_EM_GATE_3_GRAY, -1, -1
4246 Xfake_door_4, TRUE, FALSE,
4247 EL_EM_GATE_4_GRAY, -1, -1
4250 Xfake_door_5, TRUE, FALSE,
4251 EL_EMC_GATE_5_GRAY, -1, -1
4254 Xfake_door_6, TRUE, FALSE,
4255 EL_EMC_GATE_6_GRAY, -1, -1
4258 Xfake_door_7, TRUE, FALSE,
4259 EL_EMC_GATE_7_GRAY, -1, -1
4262 Xfake_door_8, TRUE, FALSE,
4263 EL_EMC_GATE_8_GRAY, -1, -1
4266 Xfake_acid_1, TRUE, FALSE,
4267 EL_EMC_FAKE_ACID, -1, -1
4270 Xfake_acid_2, FALSE, FALSE,
4271 EL_EMC_FAKE_ACID, -1, -1
4274 Xfake_acid_3, FALSE, FALSE,
4275 EL_EMC_FAKE_ACID, -1, -1
4278 Xfake_acid_4, FALSE, FALSE,
4279 EL_EMC_FAKE_ACID, -1, -1
4282 Xfake_acid_5, FALSE, FALSE,
4283 EL_EMC_FAKE_ACID, -1, -1
4286 Xfake_acid_6, FALSE, FALSE,
4287 EL_EMC_FAKE_ACID, -1, -1
4290 Xfake_acid_7, FALSE, FALSE,
4291 EL_EMC_FAKE_ACID, -1, -1
4294 Xfake_acid_8, FALSE, FALSE,
4295 EL_EMC_FAKE_ACID, -1, -1
4298 Xsteel_1, TRUE, FALSE,
4299 EL_STEELWALL, -1, -1
4302 Xsteel_2, TRUE, FALSE,
4303 EL_EMC_STEELWALL_2, -1, -1
4306 Xsteel_3, TRUE, FALSE,
4307 EL_EMC_STEELWALL_3, -1, -1
4310 Xsteel_4, TRUE, FALSE,
4311 EL_EMC_STEELWALL_4, -1, -1
4314 Xwall_1, TRUE, FALSE,
4318 Xwall_2, TRUE, FALSE,
4319 EL_EMC_WALL_14, -1, -1
4322 Xwall_3, TRUE, FALSE,
4323 EL_EMC_WALL_15, -1, -1
4326 Xwall_4, TRUE, FALSE,
4327 EL_EMC_WALL_16, -1, -1
4330 Xround_wall_1, TRUE, FALSE,
4331 EL_WALL_SLIPPERY, -1, -1
4334 Xround_wall_2, TRUE, FALSE,
4335 EL_EMC_WALL_SLIPPERY_2, -1, -1
4338 Xround_wall_3, TRUE, FALSE,
4339 EL_EMC_WALL_SLIPPERY_3, -1, -1
4342 Xround_wall_4, TRUE, FALSE,
4343 EL_EMC_WALL_SLIPPERY_4, -1, -1
4346 Xdecor_1, TRUE, FALSE,
4347 EL_EMC_WALL_8, -1, -1
4350 Xdecor_2, TRUE, FALSE,
4351 EL_EMC_WALL_6, -1, -1
4354 Xdecor_3, TRUE, FALSE,
4355 EL_EMC_WALL_4, -1, -1
4358 Xdecor_4, TRUE, FALSE,
4359 EL_EMC_WALL_7, -1, -1
4362 Xdecor_5, TRUE, FALSE,
4363 EL_EMC_WALL_5, -1, -1
4366 Xdecor_6, TRUE, FALSE,
4367 EL_EMC_WALL_9, -1, -1
4370 Xdecor_7, TRUE, FALSE,
4371 EL_EMC_WALL_10, -1, -1
4374 Xdecor_8, TRUE, FALSE,
4375 EL_EMC_WALL_1, -1, -1
4378 Xdecor_9, TRUE, FALSE,
4379 EL_EMC_WALL_2, -1, -1
4382 Xdecor_10, TRUE, FALSE,
4383 EL_EMC_WALL_3, -1, -1
4386 Xdecor_11, TRUE, FALSE,
4387 EL_EMC_WALL_11, -1, -1
4390 Xdecor_12, TRUE, FALSE,
4391 EL_EMC_WALL_12, -1, -1
4394 Xalpha_0, TRUE, FALSE,
4395 EL_CHAR('0'), -1, -1
4398 Xalpha_1, TRUE, FALSE,
4399 EL_CHAR('1'), -1, -1
4402 Xalpha_2, TRUE, FALSE,
4403 EL_CHAR('2'), -1, -1
4406 Xalpha_3, TRUE, FALSE,
4407 EL_CHAR('3'), -1, -1
4410 Xalpha_4, TRUE, FALSE,
4411 EL_CHAR('4'), -1, -1
4414 Xalpha_5, TRUE, FALSE,
4415 EL_CHAR('5'), -1, -1
4418 Xalpha_6, TRUE, FALSE,
4419 EL_CHAR('6'), -1, -1
4422 Xalpha_7, TRUE, FALSE,
4423 EL_CHAR('7'), -1, -1
4426 Xalpha_8, TRUE, FALSE,
4427 EL_CHAR('8'), -1, -1
4430 Xalpha_9, TRUE, FALSE,
4431 EL_CHAR('9'), -1, -1
4434 Xalpha_excla, TRUE, FALSE,
4435 EL_CHAR('!'), -1, -1
4438 Xalpha_quote, TRUE, FALSE,
4439 EL_CHAR('"'), -1, -1
4442 Xalpha_comma, TRUE, FALSE,
4443 EL_CHAR(','), -1, -1
4446 Xalpha_minus, TRUE, FALSE,
4447 EL_CHAR('-'), -1, -1
4450 Xalpha_perio, TRUE, FALSE,
4451 EL_CHAR('.'), -1, -1
4454 Xalpha_colon, TRUE, FALSE,
4455 EL_CHAR(':'), -1, -1
4458 Xalpha_quest, TRUE, FALSE,
4459 EL_CHAR('?'), -1, -1
4462 Xalpha_a, TRUE, FALSE,
4463 EL_CHAR('A'), -1, -1
4466 Xalpha_b, TRUE, FALSE,
4467 EL_CHAR('B'), -1, -1
4470 Xalpha_c, TRUE, FALSE,
4471 EL_CHAR('C'), -1, -1
4474 Xalpha_d, TRUE, FALSE,
4475 EL_CHAR('D'), -1, -1
4478 Xalpha_e, TRUE, FALSE,
4479 EL_CHAR('E'), -1, -1
4482 Xalpha_f, TRUE, FALSE,
4483 EL_CHAR('F'), -1, -1
4486 Xalpha_g, TRUE, FALSE,
4487 EL_CHAR('G'), -1, -1
4490 Xalpha_h, TRUE, FALSE,
4491 EL_CHAR('H'), -1, -1
4494 Xalpha_i, TRUE, FALSE,
4495 EL_CHAR('I'), -1, -1
4498 Xalpha_j, TRUE, FALSE,
4499 EL_CHAR('J'), -1, -1
4502 Xalpha_k, TRUE, FALSE,
4503 EL_CHAR('K'), -1, -1
4506 Xalpha_l, TRUE, FALSE,
4507 EL_CHAR('L'), -1, -1
4510 Xalpha_m, TRUE, FALSE,
4511 EL_CHAR('M'), -1, -1
4514 Xalpha_n, TRUE, FALSE,
4515 EL_CHAR('N'), -1, -1
4518 Xalpha_o, TRUE, FALSE,
4519 EL_CHAR('O'), -1, -1
4522 Xalpha_p, TRUE, FALSE,
4523 EL_CHAR('P'), -1, -1
4526 Xalpha_q, TRUE, FALSE,
4527 EL_CHAR('Q'), -1, -1
4530 Xalpha_r, TRUE, FALSE,
4531 EL_CHAR('R'), -1, -1
4534 Xalpha_s, TRUE, FALSE,
4535 EL_CHAR('S'), -1, -1
4538 Xalpha_t, TRUE, FALSE,
4539 EL_CHAR('T'), -1, -1
4542 Xalpha_u, TRUE, FALSE,
4543 EL_CHAR('U'), -1, -1
4546 Xalpha_v, TRUE, FALSE,
4547 EL_CHAR('V'), -1, -1
4550 Xalpha_w, TRUE, FALSE,
4551 EL_CHAR('W'), -1, -1
4554 Xalpha_x, TRUE, FALSE,
4555 EL_CHAR('X'), -1, -1
4558 Xalpha_y, TRUE, FALSE,
4559 EL_CHAR('Y'), -1, -1
4562 Xalpha_z, TRUE, FALSE,
4563 EL_CHAR('Z'), -1, -1
4566 Xalpha_arrow_e, TRUE, FALSE,
4567 EL_CHAR('>'), -1, -1
4570 Xalpha_arrow_w, TRUE, FALSE,
4571 EL_CHAR('<'), -1, -1
4574 Xalpha_copyr, TRUE, FALSE,
4575 EL_CHAR('©'), -1, -1
4578 Xalpha_copyr, TRUE, FALSE,
4579 EL_CHAR('©'), -1, -1
4583 Xboom_bug, FALSE, FALSE,
4584 EL_BUG, ACTION_EXPLODING, -1
4587 Xboom_bomb, FALSE, FALSE,
4588 EL_BOMB, ACTION_EXPLODING, -1
4591 Xboom_android, FALSE, FALSE,
4592 EL_EMC_ANDROID, ACTION_OTHER, -1
4595 Xboom_1, FALSE, FALSE,
4596 EL_DEFAULT, ACTION_EXPLODING, -1
4599 Xboom_2, FALSE, FALSE,
4600 EL_DEFAULT, ACTION_EXPLODING, -1
4603 Znormal, FALSE, FALSE,
4607 Zdynamite, FALSE, FALSE,
4611 Zplayer, FALSE, FALSE,
4615 ZBORDER, FALSE, FALSE,
4625 static struct Mapping_EM_to_RND_player
4634 em_player_mapping_list[] =
4638 EL_PLAYER_1, ACTION_MOVING, MV_BIT_UP,
4642 EL_PLAYER_1, ACTION_MOVING, MV_BIT_RIGHT,
4646 EL_PLAYER_1, ACTION_MOVING, MV_BIT_DOWN,
4650 EL_PLAYER_1, ACTION_MOVING, MV_BIT_LEFT,
4654 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_UP,
4658 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_RIGHT,
4662 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_DOWN,
4666 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_LEFT,
4670 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_UP,
4674 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_RIGHT,
4678 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_DOWN,
4682 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_LEFT,
4686 EL_PLAYER_2, ACTION_MOVING, MV_BIT_UP,
4690 EL_PLAYER_2, ACTION_MOVING, MV_BIT_RIGHT,
4694 EL_PLAYER_2, ACTION_MOVING, MV_BIT_DOWN,
4698 EL_PLAYER_2, ACTION_MOVING, MV_BIT_LEFT,
4702 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_UP,
4706 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_RIGHT,
4710 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_DOWN,
4714 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_LEFT,
4718 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_UP,
4722 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_RIGHT,
4726 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_DOWN,
4730 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_LEFT,
4734 EL_PLAYER_1, ACTION_DEFAULT, -1,
4738 EL_PLAYER_2, ACTION_DEFAULT, -1,
4747 int map_element_RND_to_EM(int element_rnd)
4749 static unsigned short mapping_RND_to_EM[NUM_FILE_ELEMENTS];
4750 static boolean mapping_initialized = FALSE;
4752 if (!mapping_initialized)
4756 /* return "Xalpha_quest" for all undefined elements in mapping array */
4757 for (i = 0; i < NUM_FILE_ELEMENTS; i++)
4758 mapping_RND_to_EM[i] = Xalpha_quest;
4760 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
4761 if (em_object_mapping_list[i].is_rnd_to_em_mapping)
4762 mapping_RND_to_EM[em_object_mapping_list[i].element_rnd] =
4763 em_object_mapping_list[i].element_em;
4765 mapping_initialized = TRUE;
4768 if (element_rnd >= 0 && element_rnd < NUM_FILE_ELEMENTS)
4769 return mapping_RND_to_EM[element_rnd];
4771 Error(ERR_WARN, "invalid RND level element %d", element_rnd);
4776 int map_element_EM_to_RND(int element_em)
4778 static unsigned short mapping_EM_to_RND[TILE_MAX];
4779 static boolean mapping_initialized = FALSE;
4781 if (!mapping_initialized)
4785 /* return "EL_UNKNOWN" for all undefined elements in mapping array */
4786 for (i = 0; i < TILE_MAX; i++)
4787 mapping_EM_to_RND[i] = EL_UNKNOWN;
4789 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
4790 mapping_EM_to_RND[em_object_mapping_list[i].element_em] =
4791 em_object_mapping_list[i].element_rnd;
4793 mapping_initialized = TRUE;
4796 if (element_em >= 0 && element_em < TILE_MAX)
4797 return mapping_EM_to_RND[element_em];
4799 Error(ERR_WARN, "invalid EM level element %d", element_em);
4804 void map_android_clone_elements_RND_to_EM(struct LevelInfo *level)
4806 struct LevelInfo_EM *level_em = level->native_em_level;
4807 struct LEVEL *lev = level_em->lev;
4810 for (i = 0; i < level->num_android_clone_elements; i++)
4812 int element_rnd = level->android_clone_element[i];
4813 int element_em = map_element_RND_to_EM(element_rnd);
4815 for (j = 0; em_object_mapping_list[j].element_em != -1; j++)
4816 if (em_object_mapping_list[j].element_rnd == element_rnd)
4817 lev->android_array[em_object_mapping_list[j].element_em] = element_em;
4821 void map_android_clone_elements_EM_to_RND(struct LevelInfo *level)
4823 struct LevelInfo_EM *level_em = level->native_em_level;
4824 struct LEVEL *lev = level_em->lev;
4827 level->num_android_clone_elements = 0;
4829 for (i = 0; i < TILE_MAX; i++)
4831 int element_em = lev->android_array[i];
4833 boolean element_found = FALSE;
4835 if (element_em == Xblank)
4838 element_rnd = map_element_EM_to_RND(element_em);
4840 for (j = 0; j < level->num_android_clone_elements; j++)
4841 if (level->android_clone_element[j] == element_rnd)
4842 element_found = TRUE;
4846 level->android_clone_element[level->num_android_clone_elements++] =
4849 if (level->num_android_clone_elements == MAX_ANDROID_ELEMENTS)
4854 if (level->num_android_clone_elements == 0)
4856 level->num_android_clone_elements = 1;
4857 level->android_clone_element[0] = EL_EMPTY;
4863 int map_element_RND_to_EM(int element_rnd)
4865 static unsigned short mapping_RND_to_EM[NUM_FILE_ELEMENTS];
4866 static boolean mapping_initialized = FALSE;
4873 mapping_RND_to_EM_list[] =
4875 { Xblank, EL_EMPTY },
4876 { Xstone, EL_ROCK },
4878 { Xbug_n, EL_BUG_UP },
4879 { Xbug_e, EL_BUG_RIGHT },
4880 { Xbug_s, EL_BUG_DOWN },
4881 { Xbug_w, EL_BUG_LEFT },
4882 { Xtank_n, EL_SPACESHIP_UP },
4883 { Xtank_e, EL_SPACESHIP_RIGHT },
4884 { Xtank_s, EL_SPACESHIP_DOWN },
4885 { Xtank_w, EL_SPACESHIP_LEFT },
4886 { Xandroid, EL_EMC_ANDROID },
4887 { Xandroid_1_n, EL_EMC_ANDROID_UP },
4888 { Xandroid_1_e, EL_EMC_ANDROID_RIGHT },
4889 { Xandroid_1_w, EL_EMC_ANDROID_LEFT },
4890 { Xandroid_1_s, EL_EMC_ANDROID_DOWN },
4891 { Xspring, EL_SPRING },
4892 { Xeater_n, EL_YAMYAM },
4893 { Xalien, EL_ROBOT },
4894 { Xemerald, EL_EMERALD },
4895 { Xdiamond, EL_DIAMOND },
4896 { Xdrip_fall, EL_AMOEBA_DROP },
4898 { Xballoon, EL_BALLOON },
4899 { Xgrass, EL_EMC_GRASS },
4901 { Xacid_ne, EL_ACID_POOL_TOPRIGHT },
4902 { Xacid_se, EL_ACID_POOL_BOTTOMRIGHT },
4903 { Xacid_s, EL_ACID_POOL_BOTTOM },
4904 { Xacid_sw, EL_ACID_POOL_BOTTOMLEFT },
4905 { Xacid_nw, EL_ACID_POOL_TOPLEFT },
4906 { Xacid_1, EL_ACID },
4907 { Xball_1, EL_EMC_MAGIC_BALL },
4908 { Xgrow_ns, EL_EMC_GROW },
4909 { Xwonderwall, EL_MAGIC_WALL },
4910 { Xamoeba_1, EL_AMOEBA_WET },
4911 { Xdoor_1, EL_EM_GATE_1 },
4912 { Xdoor_2, EL_EM_GATE_2 },
4913 { Xdoor_3, EL_EM_GATE_3 },
4914 { Xdoor_4, EL_EM_GATE_4 },
4915 { Xdoor_5, EL_EMC_GATE_5 },
4916 { Xdoor_6, EL_EMC_GATE_6 },
4917 { Xdoor_7, EL_EMC_GATE_7 },
4918 { Xdoor_8, EL_EMC_GATE_8 },
4919 { Xkey_1, EL_EM_KEY_1 },
4920 { Xkey_2, EL_EM_KEY_2 },
4921 { Xkey_3, EL_EM_KEY_3 },
4922 { Xkey_4, EL_EM_KEY_4 },
4923 { Xkey_5, EL_EMC_KEY_5 },
4924 { Xkey_6, EL_EMC_KEY_6 },
4925 { Xkey_7, EL_EMC_KEY_7 },
4926 { Xkey_8, EL_EMC_KEY_8 },
4927 { Xwind_n, EL_BALLOON_SWITCH_UP },
4928 { Xwind_e, EL_BALLOON_SWITCH_RIGHT },
4929 { Xwind_s, EL_BALLOON_SWITCH_DOWN },
4930 { Xwind_w, EL_BALLOON_SWITCH_LEFT },
4931 { Xwind_nesw, EL_BALLOON_SWITCH_ANY },
4932 { Xwind_stop, EL_BALLOON_SWITCH_NONE },
4933 { Xexit, EL_EXIT_CLOSED },
4934 { Xexit_1, EL_EXIT_OPEN },
4935 { Xdynamite, EL_DYNAMITE },
4936 { Xdynamite_1, EL_DYNAMITE_ACTIVE },
4937 { Xbumper, EL_EMC_BUMPER },
4938 { Xwheel, EL_ROBOT_WHEEL },
4939 { Xswitch, EL_UNKNOWN },
4940 { Xsand, EL_QUICKSAND_EMPTY },
4941 { Xsand_stone, EL_QUICKSAND_FULL },
4942 { Xplant, EL_EMC_PLANT },
4943 { Xlenses, EL_EMC_LENSES },
4944 { Xmagnify, EL_EMC_MAGNIFIER },
4945 { Xdripper, EL_UNKNOWN },
4946 { Xfake_blank, EL_INVISIBLE_WALL },
4947 { Xfake_grass, EL_INVISIBLE_SAND },
4948 { Xfake_door_1, EL_EM_GATE_1_GRAY },
4949 { Xfake_door_2, EL_EM_GATE_2_GRAY },
4950 { Xfake_door_3, EL_EM_GATE_3_GRAY },
4951 { Xfake_door_4, EL_EM_GATE_4_GRAY },
4952 { Xfake_door_5, EL_EMC_GATE_5_GRAY },
4953 { Xfake_door_6, EL_EMC_GATE_6_GRAY },
4954 { Xfake_door_7, EL_EMC_GATE_7_GRAY },
4955 { Xfake_door_8, EL_EMC_GATE_8_GRAY },
4956 { Xsteel_1, EL_STEELWALL },
4957 { Xsteel_2, EL_UNKNOWN },
4958 { Xsteel_3, EL_EMC_STEELWALL_1 },
4959 { Xsteel_4, EL_UNKNOWN },
4960 { Xwall_1, EL_WALL },
4961 { Xwall_2, EL_UNKNOWN },
4962 { Xwall_3, EL_UNKNOWN },
4963 { Xwall_4, EL_UNKNOWN },
4964 { Xround_wall_1, EL_WALL_SLIPPERY },
4965 { Xround_wall_2, EL_UNKNOWN },
4966 { Xround_wall_3, EL_UNKNOWN },
4967 { Xround_wall_4, EL_UNKNOWN },
4968 { Xdecor_1, EL_UNKNOWN },
4969 { Xdecor_2, EL_EMC_WALL_6 },
4970 { Xdecor_3, EL_EMC_WALL_4 },
4971 { Xdecor_4, EL_EMC_WALL_5 },
4972 { Xdecor_5, EL_EMC_WALL_7 },
4973 { Xdecor_6, EL_EMC_WALL_8 },
4974 { Xdecor_7, EL_UNKNOWN },
4975 { Xdecor_8, EL_EMC_WALL_1 },
4976 { Xdecor_9, EL_EMC_WALL_2 },
4977 { Xdecor_10, EL_EMC_WALL_3 },
4978 { Xdecor_11, EL_UNKNOWN },
4979 { Xdecor_12, EL_UNKNOWN },
4980 { Xalpha_0, EL_CHAR('0') },
4981 { Xalpha_1, EL_CHAR('1') },
4982 { Xalpha_2, EL_CHAR('2') },
4983 { Xalpha_3, EL_CHAR('3') },
4984 { Xalpha_4, EL_CHAR('4') },
4985 { Xalpha_5, EL_CHAR('5') },
4986 { Xalpha_6, EL_CHAR('6') },
4987 { Xalpha_7, EL_CHAR('7') },
4988 { Xalpha_8, EL_CHAR('8') },
4989 { Xalpha_9, EL_CHAR('9') },
4990 { Xalpha_excla, EL_CHAR('!') },
4991 { Xalpha_quote, EL_CHAR('"') },
4992 { Xalpha_comma, EL_CHAR(',') },
4993 { Xalpha_minus, EL_CHAR('-') },
4994 { Xalpha_perio, EL_CHAR('.') },
4995 { Xalpha_colon, EL_CHAR(':') },
4996 { Xalpha_quest, EL_CHAR('?') },
4997 { Xalpha_a, EL_CHAR('A') },
4998 { Xalpha_b, EL_CHAR('B') },
4999 { Xalpha_c, EL_CHAR('C') },
5000 { Xalpha_d, EL_CHAR('D') },
5001 { Xalpha_e, EL_CHAR('E') },
5002 { Xalpha_f, EL_CHAR('F') },
5003 { Xalpha_g, EL_CHAR('G') },
5004 { Xalpha_h, EL_CHAR('H') },
5005 { Xalpha_i, EL_CHAR('I') },
5006 { Xalpha_j, EL_CHAR('J') },
5007 { Xalpha_k, EL_CHAR('K') },
5008 { Xalpha_l, EL_CHAR('L') },
5009 { Xalpha_m, EL_CHAR('M') },
5010 { Xalpha_n, EL_CHAR('N') },
5011 { Xalpha_o, EL_CHAR('O') },
5012 { Xalpha_p, EL_CHAR('P') },
5013 { Xalpha_q, EL_CHAR('Q') },
5014 { Xalpha_r, EL_CHAR('R') },
5015 { Xalpha_s, EL_CHAR('S') },
5016 { Xalpha_t, EL_CHAR('T') },
5017 { Xalpha_u, EL_CHAR('U') },
5018 { Xalpha_v, EL_CHAR('V') },
5019 { Xalpha_w, EL_CHAR('W') },
5020 { Xalpha_x, EL_CHAR('X') },
5021 { Xalpha_y, EL_CHAR('Y') },
5022 { Xalpha_z, EL_CHAR('Z') },
5023 { Xalpha_arrow_e, EL_CHAR('>') },
5024 { Xalpha_arrow_w, EL_CHAR('<') },
5025 { Xalpha_copyr, EL_CHAR('©') },
5027 { Zplayer, EL_PLAYER_1 },
5028 { Zplayer, EL_PLAYER_2 },
5029 { Zplayer, EL_PLAYER_3 },
5030 { Zplayer, EL_PLAYER_4 },
5032 { ZBORDER, EL_EMC_LEVEL_BORDER },
5037 if (!mapping_initialized)
5041 /* return "Xalpha_quest" for all undefined elements in mapping array */
5042 for (i = 0; i < NUM_FILE_ELEMENTS; i++)
5043 mapping_RND_to_EM[i] = Xalpha_quest;
5045 for (i = 0; mapping_RND_to_EM_list[i].element_rnd != -1; i++)
5046 mapping_RND_to_EM[mapping_RND_to_EM_list[i].element_rnd] =
5047 mapping_RND_to_EM_list[i].element_em;
5049 mapping_initialized = TRUE;
5052 if (element_rnd >= 0 && element_rnd < NUM_FILE_ELEMENTS)
5053 return mapping_RND_to_EM[element_rnd];
5055 Error(ERR_WARN, "invalid RND level element %d", element_rnd);
5060 int map_element_EM_to_RND(int element_em)
5062 static unsigned short mapping_EM_to_RND[TILE_MAX];
5063 static boolean mapping_initialized = FALSE;
5070 em_object_mapping_list[] =
5072 { Xblank, EL_EMPTY },
5073 { Yacid_splash_eB, EL_EMPTY },
5074 { Yacid_splash_wB, EL_EMPTY },
5076 #ifdef EM_ENGINE_BAD_ROLL
5077 { Xstone_force_e, EL_ROCK },
5078 { Xstone_force_w, EL_ROCK },
5079 { Xnut_force_e, EL_NUT },
5080 { Xnut_force_w, EL_NUT },
5081 { Xspring_force_e, EL_SPRING },
5082 { Xspring_force_w, EL_SPRING },
5083 { Xemerald_force_e, EL_EMERALD },
5084 { Xemerald_force_w, EL_EMERALD },
5085 { Xdiamond_force_e, EL_DIAMOND },
5086 { Xdiamond_force_w, EL_DIAMOND },
5087 { Xbomb_force_e, EL_BOMB },
5088 { Xbomb_force_w, EL_BOMB },
5091 { Xstone, EL_ROCK },
5092 { Xstone_pause, EL_ROCK },
5093 { Xstone_fall, EL_ROCK },
5094 { Ystone_s, EL_ROCK },
5095 { Ystone_sB, EL_ROCK },
5096 { Ystone_e, EL_ROCK },
5097 { Ystone_eB, EL_ROCK },
5098 { Ystone_w, EL_ROCK },
5099 { Ystone_wB, EL_ROCK },
5101 { Xnut_pause, EL_NUT },
5102 { Xnut_fall, EL_NUT },
5104 { Ynut_sB, EL_NUT },
5106 { Ynut_eB, EL_NUT },
5108 { Ynut_wB, EL_NUT },
5109 { Xbug_n, EL_BUG_UP },
5110 { Xbug_e, EL_BUG_RIGHT },
5111 { Xbug_s, EL_BUG_DOWN },
5112 { Xbug_w, EL_BUG_LEFT },
5113 { Xbug_gon, EL_BUG_UP },
5114 { Xbug_goe, EL_BUG_RIGHT },
5115 { Xbug_gos, EL_BUG_DOWN },
5116 { Xbug_gow, EL_BUG_LEFT },
5117 { Ybug_n, EL_BUG_UP },
5118 { Ybug_nB, EL_BUG_UP },
5119 { Ybug_e, EL_BUG_RIGHT },
5120 { Ybug_eB, EL_BUG_RIGHT },
5121 { Ybug_s, EL_BUG_DOWN },
5122 { Ybug_sB, EL_BUG_DOWN },
5123 { Ybug_w, EL_BUG_LEFT },
5124 { Ybug_wB, EL_BUG_LEFT },
5125 { Ybug_w_n, EL_BUG_UP },
5126 { Ybug_n_e, EL_BUG_RIGHT },
5127 { Ybug_e_s, EL_BUG_DOWN },
5128 { Ybug_s_w, EL_BUG_LEFT },
5129 { Ybug_e_n, EL_BUG_UP },
5130 { Ybug_s_e, EL_BUG_RIGHT },
5131 { Ybug_w_s, EL_BUG_DOWN },
5132 { Ybug_n_w, EL_BUG_LEFT },
5133 { Ybug_stone, EL_ROCK },
5134 { Ybug_spring, EL_SPRING },
5135 { Xtank_n, EL_SPACESHIP_UP },
5136 { Xtank_e, EL_SPACESHIP_RIGHT },
5137 { Xtank_s, EL_SPACESHIP_DOWN },
5138 { Xtank_w, EL_SPACESHIP_LEFT },
5139 { Xtank_gon, EL_SPACESHIP_UP },
5140 { Xtank_goe, EL_SPACESHIP_RIGHT },
5141 { Xtank_gos, EL_SPACESHIP_DOWN },
5142 { Xtank_gow, EL_SPACESHIP_LEFT },
5143 { Ytank_n, EL_SPACESHIP_UP },
5144 { Ytank_nB, EL_SPACESHIP_UP },
5145 { Ytank_e, EL_SPACESHIP_RIGHT },
5146 { Ytank_eB, EL_SPACESHIP_RIGHT },
5147 { Ytank_s, EL_SPACESHIP_DOWN },
5148 { Ytank_sB, EL_SPACESHIP_DOWN },
5149 { Ytank_w, EL_SPACESHIP_LEFT },
5150 { Ytank_wB, EL_SPACESHIP_LEFT },
5151 { Ytank_w_n, EL_SPACESHIP_UP },
5152 { Ytank_n_e, EL_SPACESHIP_RIGHT },
5153 { Ytank_e_s, EL_SPACESHIP_DOWN },
5154 { Ytank_s_w, EL_SPACESHIP_LEFT },
5155 { Ytank_e_n, EL_SPACESHIP_UP },
5156 { Ytank_s_e, EL_SPACESHIP_RIGHT },
5157 { Ytank_w_s, EL_SPACESHIP_DOWN },
5158 { Ytank_n_w, EL_SPACESHIP_LEFT },
5159 { Ytank_stone, EL_ROCK },
5160 { Ytank_spring, EL_SPRING },
5161 { Xandroid, EL_EMC_ANDROID },
5162 { Xandroid_1_n, EL_EMC_ANDROID_UP },
5163 { Xandroid_2_n, EL_EMC_ANDROID_UP },
5164 { Xandroid_1_e, EL_EMC_ANDROID_RIGHT },
5165 { Xandroid_2_e, EL_EMC_ANDROID_RIGHT },
5166 { Xandroid_1_w, EL_EMC_ANDROID_LEFT },
5167 { Xandroid_2_w, EL_EMC_ANDROID_LEFT },
5168 { Xandroid_1_s, EL_EMC_ANDROID_DOWN },
5169 { Xandroid_2_s, EL_EMC_ANDROID_DOWN },
5170 { Yandroid_n, EL_EMC_ANDROID_UP },
5171 { Yandroid_nB, EL_EMC_ANDROID_UP },
5172 { Yandroid_ne, EL_EMC_ANDROID_RIGHT_UP },
5173 { Yandroid_neB, EL_EMC_ANDROID_RIGHT_UP },
5174 { Yandroid_e, EL_EMC_ANDROID_RIGHT },
5175 { Yandroid_eB, EL_EMC_ANDROID_RIGHT },
5176 { Yandroid_se, EL_EMC_ANDROID_RIGHT_DOWN },
5177 { Yandroid_seB, EL_EMC_ANDROID_RIGHT_DOWN },
5178 { Yandroid_s, EL_EMC_ANDROID_DOWN },
5179 { Yandroid_sB, EL_EMC_ANDROID_DOWN },
5180 { Yandroid_sw, EL_EMC_ANDROID_LEFT_DOWN },
5181 { Yandroid_swB, EL_EMC_ANDROID_LEFT_DOWN },
5182 { Yandroid_w, EL_EMC_ANDROID_LEFT },
5183 { Yandroid_wB, EL_EMC_ANDROID_LEFT },
5184 { Yandroid_nw, EL_EMC_ANDROID_LEFT_UP },
5185 { Yandroid_nwB, EL_EMC_ANDROID_LEFT_UP },
5186 { Xspring, EL_SPRING },
5187 { Xspring_pause, EL_SPRING },
5188 { Xspring_e, EL_SPRING },
5189 { Xspring_w, EL_SPRING },
5190 { Xspring_fall, EL_SPRING },
5191 { Yspring_s, EL_SPRING },
5192 { Yspring_sB, EL_SPRING },
5193 { Yspring_e, EL_SPRING },
5194 { Yspring_eB, EL_SPRING },
5195 { Yspring_w, EL_SPRING },
5196 { Yspring_wB, EL_SPRING },
5197 { Yspring_kill_e, EL_SPRING },
5198 { Yspring_kill_eB, EL_SPRING },
5199 { Yspring_kill_w, EL_SPRING },
5200 { Yspring_kill_wB, EL_SPRING },
5201 { Xeater_n, EL_YAMYAM },
5202 { Xeater_e, EL_YAMYAM },
5203 { Xeater_w, EL_YAMYAM },
5204 { Xeater_s, EL_YAMYAM },
5205 { Yeater_n, EL_YAMYAM },
5206 { Yeater_nB, EL_YAMYAM },
5207 { Yeater_e, EL_YAMYAM },
5208 { Yeater_eB, EL_YAMYAM },
5209 { Yeater_s, EL_YAMYAM },
5210 { Yeater_sB, EL_YAMYAM },
5211 { Yeater_w, EL_YAMYAM },
5212 { Yeater_wB, EL_YAMYAM },
5213 { Yeater_stone, EL_ROCK },
5214 { Yeater_spring, EL_SPRING },
5215 { Xalien, EL_ROBOT },
5216 { Xalien_pause, EL_ROBOT },
5217 { Yalien_n, EL_ROBOT },
5218 { Yalien_nB, EL_ROBOT },
5219 { Yalien_e, EL_ROBOT },
5220 { Yalien_eB, EL_ROBOT },
5221 { Yalien_s, EL_ROBOT },
5222 { Yalien_sB, EL_ROBOT },
5223 { Yalien_w, EL_ROBOT },
5224 { Yalien_wB, EL_ROBOT },
5225 { Yalien_stone, EL_ROCK },
5226 { Yalien_spring, EL_SPRING },
5227 { Xemerald, EL_EMERALD },
5228 { Xemerald_pause, EL_EMERALD },
5229 { Xemerald_fall, EL_EMERALD },
5230 { Xemerald_shine, EL_EMERALD },
5231 { Yemerald_s, EL_EMERALD },
5232 { Yemerald_sB, EL_EMERALD },
5233 { Yemerald_e, EL_EMERALD },
5234 { Yemerald_eB, EL_EMERALD },
5235 { Yemerald_w, EL_EMERALD },
5236 { Yemerald_wB, EL_EMERALD },
5237 { Yemerald_eat, EL_EMERALD },
5238 { Yemerald_stone, EL_ROCK },
5239 { Xdiamond, EL_DIAMOND },
5240 { Xdiamond_pause, EL_DIAMOND },
5241 { Xdiamond_fall, EL_DIAMOND },
5242 { Xdiamond_shine, EL_DIAMOND },
5243 { Ydiamond_s, EL_DIAMOND },
5244 { Ydiamond_sB, EL_DIAMOND },
5245 { Ydiamond_e, EL_DIAMOND },
5246 { Ydiamond_eB, EL_DIAMOND },
5247 { Ydiamond_w, EL_DIAMOND },
5248 { Ydiamond_wB, EL_DIAMOND },
5249 { Ydiamond_eat, EL_DIAMOND },
5250 { Ydiamond_stone, EL_ROCK },
5251 { Xdrip_fall, EL_AMOEBA_DROP },
5252 { Xdrip_stretch, EL_AMOEBA_DROP },
5253 { Xdrip_stretchB, EL_AMOEBA_DROP },
5254 { Xdrip_eat, EL_AMOEBA_DROP },
5255 { Ydrip_s1, EL_AMOEBA_DROP },
5256 { Ydrip_s1B, EL_AMOEBA_DROP },
5257 { Ydrip_s2, EL_AMOEBA_DROP },
5258 { Ydrip_s2B, EL_AMOEBA_DROP },
5260 { Xbomb_pause, EL_BOMB },
5261 { Xbomb_fall, EL_BOMB },
5262 { Ybomb_s, EL_BOMB },
5263 { Ybomb_sB, EL_BOMB },
5264 { Ybomb_e, EL_BOMB },
5265 { Ybomb_eB, EL_BOMB },
5266 { Ybomb_w, EL_BOMB },
5267 { Ybomb_wB, EL_BOMB },
5268 { Ybomb_eat, EL_BOMB },
5269 { Xballoon, EL_BALLOON },
5270 { Yballoon_n, EL_BALLOON },
5271 { Yballoon_nB, EL_BALLOON },
5272 { Yballoon_e, EL_BALLOON },
5273 { Yballoon_eB, EL_BALLOON },
5274 { Yballoon_s, EL_BALLOON },
5275 { Yballoon_sB, EL_BALLOON },
5276 { Yballoon_w, EL_BALLOON },
5277 { Yballoon_wB, EL_BALLOON },
5278 { Xgrass, EL_SAND },
5279 { Ygrass_nB, EL_SAND },
5280 { Ygrass_eB, EL_SAND },
5281 { Ygrass_sB, EL_SAND },
5282 { Ygrass_wB, EL_SAND },
5284 { Ydirt_nB, EL_SAND },
5285 { Ydirt_eB, EL_SAND },
5286 { Ydirt_sB, EL_SAND },
5287 { Ydirt_wB, EL_SAND },
5288 { Xacid_ne, EL_ACID_POOL_TOPRIGHT },
5289 { Xacid_se, EL_ACID_POOL_BOTTOMRIGHT },
5290 { Xacid_s, EL_ACID_POOL_BOTTOM },
5291 { Xacid_sw, EL_ACID_POOL_BOTTOMLEFT },
5292 { Xacid_nw, EL_ACID_POOL_TOPLEFT },
5293 { Xacid_1, EL_ACID },
5294 { Xacid_2, EL_ACID },
5295 { Xacid_3, EL_ACID },
5296 { Xacid_4, EL_ACID },
5297 { Xacid_5, EL_ACID },
5298 { Xacid_6, EL_ACID },
5299 { Xacid_7, EL_ACID },
5300 { Xacid_8, EL_ACID },
5301 { Xball_1, EL_EMC_MAGIC_BALL },
5302 { Xball_1B, EL_EMC_MAGIC_BALL },
5303 { Xball_2, EL_EMC_MAGIC_BALL },
5304 { Xball_2B, EL_EMC_MAGIC_BALL },
5305 { Yball_eat, EL_EMC_MAGIC_BALL },
5306 { Xgrow_ns, EL_EMC_GROW },
5307 { Ygrow_ns_eat, EL_EMC_GROW },
5308 { Xgrow_ew, EL_EMC_GROW },
5309 { Ygrow_ew_eat, EL_EMC_GROW },
5310 { Xwonderwall, EL_MAGIC_WALL },
5311 { XwonderwallB, EL_MAGIC_WALL },
5312 { Xamoeba_1, EL_AMOEBA_WET },
5313 { Xamoeba_2, EL_AMOEBA_WET },
5314 { Xamoeba_3, EL_AMOEBA_WET },
5315 { Xamoeba_4, EL_AMOEBA_WET },
5316 { Xamoeba_5, EL_AMOEBA_WET },
5317 { Xamoeba_6, EL_AMOEBA_WET },
5318 { Xamoeba_7, EL_AMOEBA_WET },
5319 { Xamoeba_8, EL_AMOEBA_WET },
5320 { Xdoor_1, EL_EM_GATE_1 },
5321 { Xdoor_2, EL_EM_GATE_2 },
5322 { Xdoor_3, EL_EM_GATE_3 },
5323 { Xdoor_4, EL_EM_GATE_4 },
5324 { Xdoor_5, EL_EMC_GATE_5 },
5325 { Xdoor_6, EL_EMC_GATE_6 },
5326 { Xdoor_7, EL_EMC_GATE_7 },
5327 { Xdoor_8, EL_EMC_GATE_8 },
5328 { Xkey_1, EL_EM_KEY_1 },
5329 { Xkey_2, EL_EM_KEY_2 },
5330 { Xkey_3, EL_EM_KEY_3 },
5331 { Xkey_4, EL_EM_KEY_4 },
5332 { Xkey_5, EL_EMC_KEY_5 },
5333 { Xkey_6, EL_EMC_KEY_6 },
5334 { Xkey_7, EL_EMC_KEY_7 },
5335 { Xkey_8, EL_EMC_KEY_8 },
5336 { Xwind_n, EL_BALLOON_SWITCH_UP },
5337 { Xwind_e, EL_BALLOON_SWITCH_RIGHT },
5338 { Xwind_s, EL_BALLOON_SWITCH_DOWN },
5339 { Xwind_w, EL_BALLOON_SWITCH_LEFT },
5340 { Xwind_nesw, EL_BALLOON_SWITCH_ANY },
5341 { Xwind_stop, EL_BALLOON_SWITCH_NONE },
5342 { Xexit, EL_EXIT_CLOSED },
5343 { Xexit_1, EL_EXIT_OPEN },
5344 { Xexit_2, EL_EXIT_OPEN },
5345 { Xexit_3, EL_EXIT_OPEN },
5346 { Xdynamite, EL_DYNAMITE },
5347 { Ydynamite_eat, EL_DYNAMITE },
5348 { Xdynamite_1, EL_DYNAMITE_ACTIVE },
5349 { Xdynamite_2, EL_DYNAMITE_ACTIVE },
5350 { Xdynamite_3, EL_DYNAMITE_ACTIVE },
5351 { Xdynamite_4, EL_DYNAMITE_ACTIVE },
5352 { Xbumper, EL_EMC_BUMPER },
5353 { XbumperB, EL_EMC_BUMPER },
5354 { Xwheel, EL_ROBOT_WHEEL },
5355 { XwheelB, EL_ROBOT_WHEEL },
5356 { Xswitch, EL_UNKNOWN },
5357 { XswitchB, EL_UNKNOWN },
5358 { Xsand, EL_QUICKSAND_EMPTY },
5359 { Xsand_stone, EL_QUICKSAND_FULL },
5360 { Xsand_stonein_1, EL_QUICKSAND_FULL },
5361 { Xsand_stonein_2, EL_QUICKSAND_FULL },
5362 { Xsand_stonein_3, EL_QUICKSAND_FULL },
5363 { Xsand_stonein_4, EL_QUICKSAND_FULL },
5364 { Xsand_stonesand_1, EL_QUICKSAND_FULL },
5365 { Xsand_stonesand_2, EL_QUICKSAND_FULL },
5366 { Xsand_stonesand_3, EL_QUICKSAND_FULL },
5367 { Xsand_stonesand_4, EL_QUICKSAND_FULL },
5368 { Xsand_stoneout_1, EL_QUICKSAND_FULL },
5369 { Xsand_stoneout_2, EL_QUICKSAND_FULL },
5370 { Xsand_sandstone_1, EL_QUICKSAND_FULL },
5371 { Xsand_sandstone_2, EL_QUICKSAND_FULL },
5372 { Xsand_sandstone_3, EL_QUICKSAND_FULL },
5373 { Xsand_sandstone_4, EL_QUICKSAND_FULL },
5374 { Xplant, EL_EMC_PLANT },
5375 { Yplant, EL_EMC_PLANT },
5376 { Xlenses, EL_EMC_LENSES },
5377 { Xmagnify, EL_EMC_MAGNIFIER },
5378 { Xdripper, EL_UNKNOWN },
5379 { XdripperB, EL_UNKNOWN },
5380 { Xfake_blank, EL_INVISIBLE_WALL },
5381 { Xfake_blankB, EL_INVISIBLE_WALL },
5382 { Xfake_grass, EL_INVISIBLE_SAND },
5383 { Xfake_grassB, EL_INVISIBLE_SAND },
5384 { Xfake_door_1, EL_EM_GATE_1_GRAY },
5385 { Xfake_door_2, EL_EM_GATE_2_GRAY },
5386 { Xfake_door_3, EL_EM_GATE_3_GRAY },
5387 { Xfake_door_4, EL_EM_GATE_4_GRAY },
5388 { Xfake_door_5, EL_EMC_GATE_5_GRAY },
5389 { Xfake_door_6, EL_EMC_GATE_6_GRAY },
5390 { Xfake_door_7, EL_EMC_GATE_7_GRAY },
5391 { Xfake_door_8, EL_EMC_GATE_8_GRAY },
5392 { Xsteel_1, EL_STEELWALL },
5393 { Xsteel_2, EL_UNKNOWN },
5394 { Xsteel_3, EL_EMC_STEELWALL_1 },
5395 { Xsteel_4, EL_UNKNOWN },
5396 { Xwall_1, EL_WALL },
5397 { Xwall_2, EL_UNKNOWN },
5398 { Xwall_3, EL_UNKNOWN },
5399 { Xwall_4, EL_UNKNOWN },
5400 { Xround_wall_1, EL_WALL_SLIPPERY },
5401 { Xround_wall_2, EL_UNKNOWN },
5402 { Xround_wall_3, EL_UNKNOWN },
5403 { Xround_wall_4, EL_UNKNOWN },
5404 { Xdecor_1, EL_UNKNOWN },
5405 { Xdecor_2, EL_EMC_WALL_6 },
5406 { Xdecor_3, EL_EMC_WALL_4 },
5407 { Xdecor_4, EL_EMC_WALL_5 },
5408 { Xdecor_5, EL_EMC_WALL_7 },
5409 { Xdecor_6, EL_EMC_WALL_8 },
5410 { Xdecor_7, EL_UNKNOWN },
5411 { Xdecor_8, EL_EMC_WALL_1 },
5412 { Xdecor_9, EL_EMC_WALL_2 },
5413 { Xdecor_10, EL_EMC_WALL_3 },
5414 { Xdecor_11, EL_UNKNOWN },
5415 { Xdecor_12, EL_UNKNOWN },
5416 { Xalpha_0, EL_CHAR('0') },
5417 { Xalpha_1, EL_CHAR('1') },
5418 { Xalpha_2, EL_CHAR('2') },
5419 { Xalpha_3, EL_CHAR('3') },
5420 { Xalpha_4, EL_CHAR('4') },
5421 { Xalpha_5, EL_CHAR('5') },
5422 { Xalpha_6, EL_CHAR('6') },
5423 { Xalpha_7, EL_CHAR('7') },
5424 { Xalpha_8, EL_CHAR('8') },
5425 { Xalpha_9, EL_CHAR('9') },
5426 { Xalpha_excla, EL_CHAR('!') },
5427 { Xalpha_quote, EL_CHAR('"') },
5428 { Xalpha_comma, EL_CHAR(',') },
5429 { Xalpha_minus, EL_CHAR('-') },
5430 { Xalpha_perio, EL_CHAR('.') },
5431 { Xalpha_colon, EL_CHAR(':') },
5432 { Xalpha_quest, EL_CHAR('?') },
5433 { Xalpha_a, EL_CHAR('A') },
5434 { Xalpha_b, EL_CHAR('B') },
5435 { Xalpha_c, EL_CHAR('C') },
5436 { Xalpha_d, EL_CHAR('D') },
5437 { Xalpha_e, EL_CHAR('E') },
5438 { Xalpha_f, EL_CHAR('F') },
5439 { Xalpha_g, EL_CHAR('G') },
5440 { Xalpha_h, EL_CHAR('H') },
5441 { Xalpha_i, EL_CHAR('I') },
5442 { Xalpha_j, EL_CHAR('J') },
5443 { Xalpha_k, EL_CHAR('K') },
5444 { Xalpha_l, EL_CHAR('L') },
5445 { Xalpha_m, EL_CHAR('M') },
5446 { Xalpha_n, EL_CHAR('N') },
5447 { Xalpha_o, EL_CHAR('O') },
5448 { Xalpha_p, EL_CHAR('P') },
5449 { Xalpha_q, EL_CHAR('Q') },
5450 { Xalpha_r, EL_CHAR('R') },
5451 { Xalpha_s, EL_CHAR('S') },
5452 { Xalpha_t, EL_CHAR('T') },
5453 { Xalpha_u, EL_CHAR('U') },
5454 { Xalpha_v, EL_CHAR('V') },
5455 { Xalpha_w, EL_CHAR('W') },
5456 { Xalpha_x, EL_CHAR('X') },
5457 { Xalpha_y, EL_CHAR('Y') },
5458 { Xalpha_z, EL_CHAR('Z') },
5459 { Xalpha_arrow_e, EL_CHAR('>') },
5460 { Xalpha_arrow_w, EL_CHAR('<') },
5461 { Xalpha_copyr, EL_CHAR('©') },
5463 { Zplayer, EL_PLAYER_1 },
5465 { ZBORDER, EL_EMC_LEVEL_BORDER },
5470 if (!mapping_initialized)
5474 /* return "EL_UNKNOWN" for all undefined elements in mapping array */
5475 for (i = 0; i < TILE_MAX; i++)
5476 mapping_EM_to_RND[i] = EL_UNKNOWN;
5478 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
5479 mapping_EM_to_RND[em_object_mapping_list[i].element_em] =
5480 em_object_mapping_list[i].element_rnd;
5482 mapping_initialized = TRUE;
5485 if (element_em >= 0 && element_em < TILE_MAX)
5486 return mapping_EM_to_RND[element_em];
5488 Error(ERR_WARN, "invalid EM level element %d", element_em);
5495 int map_direction_RND_to_EM(int direction)
5497 return (direction == MV_UP ? 0 :
5498 direction == MV_RIGHT ? 1 :
5499 direction == MV_DOWN ? 2 :
5500 direction == MV_LEFT ? 3 :
5504 int map_direction_EM_to_RND(int direction)
5506 return (direction == 0 ? MV_UP :
5507 direction == 1 ? MV_RIGHT :
5508 direction == 2 ? MV_DOWN :
5509 direction == 3 ? MV_LEFT :
5513 int get_next_element(int element)
5517 case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL;
5518 case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY;
5519 case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL;
5520 case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_ACTIVE;
5521 case EL_BD_MAGIC_WALL_FILLING: return EL_BD_MAGIC_WALL_FULL;
5522 case EL_BD_MAGIC_WALL_EMPTYING: return EL_BD_MAGIC_WALL_ACTIVE;
5523 case EL_AMOEBA_DROPPING: return EL_AMOEBA_WET;
5525 default: return element;
5530 int el_act_dir2img(int element, int action, int direction)
5532 element = GFX_ELEMENT(element);
5534 if (direction == MV_NONE)
5535 return element_info[element].graphic[action];
5537 direction = MV_DIR_TO_BIT(direction);
5539 return element_info[element].direction_graphic[action][direction];
5542 int el_act_dir2img(int element, int action, int direction)
5544 element = GFX_ELEMENT(element);
5545 direction = MV_DIR_TO_BIT(direction); /* default: MV_NONE => MV_DOWN */
5547 /* direction_graphic[][] == graphic[] for undefined direction graphics */
5548 return element_info[element].direction_graphic[action][direction];
5553 static int el_act_dir2crm(int element, int action, int direction)
5555 element = GFX_ELEMENT(element);
5557 if (direction == MV_NONE)
5558 return element_info[element].crumbled[action];
5560 direction = MV_DIR_TO_BIT(direction);
5562 return element_info[element].direction_crumbled[action][direction];
5565 static int el_act_dir2crm(int element, int action, int direction)
5567 element = GFX_ELEMENT(element);
5568 direction = MV_DIR_TO_BIT(direction); /* default: MV_NONE => MV_DOWN */
5570 /* direction_graphic[][] == graphic[] for undefined direction graphics */
5571 return element_info[element].direction_crumbled[action][direction];
5575 int el_act2img(int element, int action)
5577 element = GFX_ELEMENT(element);
5579 return element_info[element].graphic[action];
5582 int el_act2crm(int element, int action)
5584 element = GFX_ELEMENT(element);
5586 return element_info[element].crumbled[action];
5589 int el_dir2img(int element, int direction)
5591 element = GFX_ELEMENT(element);
5593 return el_act_dir2img(element, ACTION_DEFAULT, direction);
5596 int el2baseimg(int element)
5598 return element_info[element].graphic[ACTION_DEFAULT];
5601 int el2img(int element)
5603 element = GFX_ELEMENT(element);
5605 return element_info[element].graphic[ACTION_DEFAULT];
5608 int el2edimg(int element)
5610 element = GFX_ELEMENT(element);
5612 return element_info[element].special_graphic[GFX_SPECIAL_ARG_EDITOR];
5615 int el2preimg(int element)
5617 element = GFX_ELEMENT(element);
5619 return element_info[element].special_graphic[GFX_SPECIAL_ARG_PREVIEW];
5622 int font2baseimg(int font_nr)
5624 return font_info[font_nr].special_graphic[GFX_SPECIAL_ARG_DEFAULT];
5627 int getGameFrameDelay_EM(int native_em_game_frame_delay)
5629 int game_frame_delay_value;
5631 game_frame_delay_value =
5632 (tape.playing && tape.fast_forward ? FfwdFrameDelay :
5633 GameFrameDelay == GAME_FRAME_DELAY ? native_em_game_frame_delay :
5636 if (tape.playing && tape.warp_forward && !tape.pausing)
5637 game_frame_delay_value = 0;
5639 return game_frame_delay_value;
5642 unsigned int InitRND(long seed)
5644 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
5645 return InitEngineRND_EM(seed);
5647 return InitEngineRND(seed);
5650 #define DEBUG_EM_GFX 0
5652 void InitGraphicInfo_EM(void)
5654 struct Mapping_EM_to_RND_object object_mapping[TILE_MAX];
5655 struct Mapping_EM_to_RND_player player_mapping[2][SPR_MAX];
5659 if (graphic_info_em_object[0][0].bitmap == NULL)
5661 /* EM graphics not yet initialized in em_open_all() */
5667 /* always start with reliable default values */
5668 for (i = 0; i < TILE_MAX; i++)
5670 object_mapping[i].element_rnd = EL_UNKNOWN;
5671 object_mapping[i].is_backside = FALSE;
5672 object_mapping[i].action = ACTION_DEFAULT;
5673 object_mapping[i].direction = MV_NONE;
5676 /* always start with reliable default values */
5677 for (p = 0; p < 2; p++)
5679 for (i = 0; i < SPR_MAX; i++)
5681 player_mapping[p][i].element_rnd = EL_UNKNOWN;
5682 player_mapping[p][i].action = ACTION_DEFAULT;
5683 player_mapping[p][i].direction = MV_NONE;
5687 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
5689 int e = em_object_mapping_list[i].element_em;
5691 object_mapping[e].element_rnd = em_object_mapping_list[i].element_rnd;
5692 object_mapping[e].is_backside = em_object_mapping_list[i].is_backside;
5694 if (em_object_mapping_list[i].action != -1)
5695 object_mapping[e].action = em_object_mapping_list[i].action;
5697 if (em_object_mapping_list[i].direction != -1)
5698 object_mapping[e].direction =
5699 MV_DIR_FROM_BIT(em_object_mapping_list[i].direction);
5702 for (i = 0; em_player_mapping_list[i].action_em != -1; i++)
5704 int a = em_player_mapping_list[i].action_em;
5705 int p = em_player_mapping_list[i].player_nr;
5707 player_mapping[p][a].element_rnd = em_player_mapping_list[i].element_rnd;
5709 if (em_player_mapping_list[i].action != -1)
5710 player_mapping[p][a].action = em_player_mapping_list[i].action;
5712 if (em_player_mapping_list[i].direction != -1)
5713 player_mapping[p][a].direction =
5714 MV_DIR_FROM_BIT(em_player_mapping_list[i].direction);
5717 for (i = 0; i < TILE_MAX; i++)
5719 int element = object_mapping[i].element_rnd;
5720 int action = object_mapping[i].action;
5721 int direction = object_mapping[i].direction;
5722 boolean is_backside = object_mapping[i].is_backside;
5723 boolean action_removing = (action == ACTION_DIGGING ||
5724 action == ACTION_SNAPPING ||
5725 action == ACTION_COLLECTING);
5726 boolean action_exploding = ((action == ACTION_EXPLODING ||
5727 action == ACTION_SMASHED_BY_ROCK ||
5728 action == ACTION_SMASHED_BY_SPRING) &&
5729 element != EL_DIAMOND);
5730 boolean action_active = (action == ACTION_ACTIVE);
5731 boolean action_other = (action == ACTION_OTHER);
5733 for (j = 0; j < 8; j++)
5735 int effective_element = (j > 5 && i == Yacid_splash_eB ? EL_EMPTY :
5736 j > 5 && i == Yacid_splash_wB ? EL_EMPTY :
5738 i == Xdrip_stretch ? element :
5739 i == Xdrip_stretchB ? element :
5740 i == Ydrip_s1 ? element :
5741 i == Ydrip_s1B ? element :
5742 i == Xball_1B ? element :
5743 i == Xball_2 ? element :
5744 i == Xball_2B ? element :
5745 i == Yball_eat ? element :
5746 i == Ykey_1_eat ? element :
5747 i == Ykey_2_eat ? element :
5748 i == Ykey_3_eat ? element :
5749 i == Ykey_4_eat ? element :
5750 i == Ykey_5_eat ? element :
5751 i == Ykey_6_eat ? element :
5752 i == Ykey_7_eat ? element :
5753 i == Ykey_8_eat ? element :
5754 i == Ylenses_eat ? element :
5755 i == Ymagnify_eat ? element :
5756 i == Ygrass_eat ? element :
5757 i == Ydirt_eat ? element :
5758 i == Yspring_kill_e ? EL_SPRING :
5759 i == Yspring_kill_w ? EL_SPRING :
5760 i == Yemerald_stone ? EL_EMERALD :
5761 i == Ydiamond_stone ? EL_ROCK :
5762 i == Xsand_stonein_4 ? EL_EMPTY :
5763 i == Xsand_stoneout_2 ? EL_ROCK :
5764 is_backside ? EL_EMPTY :
5765 action_removing ? EL_EMPTY :
5767 int effective_action = (j < 7 ? action :
5768 i == Xdrip_stretch ? action :
5769 i == Xdrip_stretchB ? action :
5770 i == Ydrip_s1 ? action :
5771 i == Ydrip_s1B ? action :
5772 i == Xball_1B ? action :
5773 i == Xball_2 ? action :
5774 i == Xball_2B ? action :
5775 i == Yball_eat ? action :
5776 i == Ykey_1_eat ? action :
5777 i == Ykey_2_eat ? action :
5778 i == Ykey_3_eat ? action :
5779 i == Ykey_4_eat ? action :
5780 i == Ykey_5_eat ? action :
5781 i == Ykey_6_eat ? action :
5782 i == Ykey_7_eat ? action :
5783 i == Ykey_8_eat ? action :
5784 i == Ylenses_eat ? action :
5785 i == Ymagnify_eat ? action :
5786 i == Ygrass_eat ? action :
5787 i == Ydirt_eat ? action :
5788 i == Xsand_stonein_1 ? action :
5789 i == Xsand_stonein_2 ? action :
5790 i == Xsand_stonein_3 ? action :
5791 i == Xsand_stonein_4 ? action :
5792 i == Xsand_stoneout_1 ? action :
5793 i == Xsand_stoneout_2 ? action :
5794 i == Xboom_android ? ACTION_EXPLODING :
5795 action_exploding ? ACTION_EXPLODING :
5796 action_active ? action :
5797 action_other ? action :
5799 int graphic = (el_act_dir2img(effective_element, effective_action,
5801 int crumbled = (el_act_dir2crm(effective_element, effective_action,
5803 int base_graphic = el_act2img(effective_element, ACTION_DEFAULT);
5804 int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT);
5805 boolean has_crumbled_graphics = (base_crumbled != base_graphic);
5806 struct GraphicInfo *g = &graphic_info[graphic];
5807 struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
5810 /* ensure to get symmetric 3-frame, 2-delay animations as used in EM */
5811 boolean special_animation = (action != ACTION_DEFAULT &&
5812 g->anim_frames == 3 &&
5813 g->anim_delay == 2 &&
5814 g->anim_mode & ANIM_LINEAR);
5815 int sync_frame = (i == Xdrip_stretch ? 7 :
5816 i == Xdrip_stretchB ? 7 :
5817 i == Ydrip_s2 ? j + 8 :
5818 i == Ydrip_s2B ? j + 8 :
5827 i == Xfake_acid_1 ? 0 :
5828 i == Xfake_acid_2 ? 10 :
5829 i == Xfake_acid_3 ? 20 :
5830 i == Xfake_acid_4 ? 30 :
5831 i == Xfake_acid_5 ? 40 :
5832 i == Xfake_acid_6 ? 50 :
5833 i == Xfake_acid_7 ? 60 :
5834 i == Xfake_acid_8 ? 70 :
5836 i == Xball_2B ? j + 8 :
5837 i == Yball_eat ? j + 1 :
5838 i == Ykey_1_eat ? j + 1 :
5839 i == Ykey_2_eat ? j + 1 :
5840 i == Ykey_3_eat ? j + 1 :
5841 i == Ykey_4_eat ? j + 1 :
5842 i == Ykey_5_eat ? j + 1 :
5843 i == Ykey_6_eat ? j + 1 :
5844 i == Ykey_7_eat ? j + 1 :
5845 i == Ykey_8_eat ? j + 1 :
5846 i == Ylenses_eat ? j + 1 :
5847 i == Ymagnify_eat ? j + 1 :
5848 i == Ygrass_eat ? j + 1 :
5849 i == Ydirt_eat ? j + 1 :
5850 i == Xamoeba_1 ? 0 :
5851 i == Xamoeba_2 ? 1 :
5852 i == Xamoeba_3 ? 2 :
5853 i == Xamoeba_4 ? 3 :
5854 i == Xamoeba_5 ? 0 :
5855 i == Xamoeba_6 ? 1 :
5856 i == Xamoeba_7 ? 2 :
5857 i == Xamoeba_8 ? 3 :
5858 i == Xexit_2 ? j + 8 :
5859 i == Xexit_3 ? j + 16 :
5860 i == Xdynamite_1 ? 0 :
5861 i == Xdynamite_2 ? 20 :
5862 i == Xdynamite_3 ? 40 :
5863 i == Xdynamite_4 ? 60 :
5864 i == Xsand_stonein_1 ? j + 1 :
5865 i == Xsand_stonein_2 ? j + 9 :
5866 i == Xsand_stonein_3 ? j + 17 :
5867 i == Xsand_stonein_4 ? j + 25 :
5868 i == Xsand_stoneout_1 && j == 0 ? 0 :
5869 i == Xsand_stoneout_1 && j == 1 ? 0 :
5870 i == Xsand_stoneout_1 && j == 2 ? 1 :
5871 i == Xsand_stoneout_1 && j == 3 ? 2 :
5872 i == Xsand_stoneout_1 && j == 4 ? 2 :
5873 i == Xsand_stoneout_1 && j == 5 ? 3 :
5874 i == Xsand_stoneout_1 && j == 6 ? 4 :
5875 i == Xsand_stoneout_1 && j == 7 ? 4 :
5876 i == Xsand_stoneout_2 && j == 0 ? 5 :
5877 i == Xsand_stoneout_2 && j == 1 ? 6 :
5878 i == Xsand_stoneout_2 && j == 2 ? 7 :
5879 i == Xsand_stoneout_2 && j == 3 ? 8 :
5880 i == Xsand_stoneout_2 && j == 4 ? 9 :
5881 i == Xsand_stoneout_2 && j == 5 ? 11 :
5882 i == Xsand_stoneout_2 && j == 6 ? 13 :
5883 i == Xsand_stoneout_2 && j == 7 ? 15 :
5884 i == Xboom_bug && j == 1 ? 2 :
5885 i == Xboom_bug && j == 2 ? 2 :
5886 i == Xboom_bug && j == 3 ? 4 :
5887 i == Xboom_bug && j == 4 ? 4 :
5888 i == Xboom_bug && j == 5 ? 2 :
5889 i == Xboom_bug && j == 6 ? 2 :
5890 i == Xboom_bug && j == 7 ? 0 :
5891 i == Xboom_bomb && j == 1 ? 2 :
5892 i == Xboom_bomb && j == 2 ? 2 :
5893 i == Xboom_bomb && j == 3 ? 4 :
5894 i == Xboom_bomb && j == 4 ? 4 :
5895 i == Xboom_bomb && j == 5 ? 2 :
5896 i == Xboom_bomb && j == 6 ? 2 :
5897 i == Xboom_bomb && j == 7 ? 0 :
5898 i == Xboom_android && j == 7 ? 6 :
5899 i == Xboom_1 && j == 1 ? 2 :
5900 i == Xboom_1 && j == 2 ? 2 :
5901 i == Xboom_1 && j == 3 ? 4 :
5902 i == Xboom_1 && j == 4 ? 4 :
5903 i == Xboom_1 && j == 5 ? 6 :
5904 i == Xboom_1 && j == 6 ? 6 :
5905 i == Xboom_1 && j == 7 ? 8 :
5906 i == Xboom_2 && j == 0 ? 8 :
5907 i == Xboom_2 && j == 1 ? 8 :
5908 i == Xboom_2 && j == 2 ? 10 :
5909 i == Xboom_2 && j == 3 ? 10 :
5910 i == Xboom_2 && j == 4 ? 10 :
5911 i == Xboom_2 && j == 5 ? 12 :
5912 i == Xboom_2 && j == 6 ? 12 :
5913 i == Xboom_2 && j == 7 ? 12 :
5914 special_animation && j == 4 ? 3 :
5915 effective_action != action ? 0 :
5919 Bitmap *debug_bitmap = g_em->bitmap;
5920 int debug_src_x = g_em->src_x;
5921 int debug_src_y = g_em->src_y;
5924 int frame = getAnimationFrame(g->anim_frames,
5927 g->anim_start_frame,
5930 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y,
5931 g->double_movement && is_backside);
5933 g_em->bitmap = src_bitmap;
5934 g_em->src_x = src_x;
5935 g_em->src_y = src_y;
5936 g_em->src_offset_x = 0;
5937 g_em->src_offset_y = 0;
5938 g_em->dst_offset_x = 0;
5939 g_em->dst_offset_y = 0;
5940 g_em->width = TILEX;
5941 g_em->height = TILEY;
5943 g_em->crumbled_bitmap = NULL;
5944 g_em->crumbled_src_x = 0;
5945 g_em->crumbled_src_y = 0;
5946 g_em->crumbled_border_size = 0;
5948 g_em->has_crumbled_graphics = FALSE;
5949 g_em->preserve_background = FALSE;
5952 if (has_crumbled_graphics && crumbled == IMG_EMPTY_SPACE)
5953 printf("::: empty crumbled: %d [%s], %d, %d\n",
5954 effective_element, element_info[effective_element].token_name,
5955 effective_action, direction);
5958 /* if element can be crumbled, but certain action graphics are just empty
5959 space (like snapping sand with the original R'n'D graphics), do not
5960 treat these empty space graphics as crumbled graphics in EMC engine */
5961 if (has_crumbled_graphics && crumbled != IMG_EMPTY_SPACE)
5963 getGraphicSource(crumbled, frame, &src_bitmap, &src_x, &src_y);
5965 g_em->has_crumbled_graphics = TRUE;
5966 g_em->crumbled_bitmap = src_bitmap;
5967 g_em->crumbled_src_x = src_x;
5968 g_em->crumbled_src_y = src_y;
5969 g_em->crumbled_border_size = graphic_info[crumbled].border_size;
5972 if (!g->double_movement && (effective_action == ACTION_FALLING ||
5973 effective_action == ACTION_MOVING ||
5974 effective_action == ACTION_PUSHING))
5977 (effective_action == ACTION_FALLING ? MV_DOWN : direction);
5978 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? 1 : 0);
5979 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? 1 : 0);
5980 int num_steps = (i == Ydrip_s1 ||
5983 i == Ydrip_s2B ? 16 : 8);
5984 int cx = ABS(dx) * (TILEX / num_steps);
5985 int cy = ABS(dy) * (TILEY / num_steps);
5986 int step_frame = (i == Ydrip_s2 ||
5987 i == Ydrip_s2B ? j + 8 : j) + 1;
5988 int step = (is_backside ? step_frame : num_steps - step_frame);
5990 if (is_backside) /* tile where movement starts */
5992 if (dx < 0 || dy < 0)
5994 g_em->src_offset_x = cx * step;
5995 g_em->src_offset_y = cy * step;
5999 g_em->dst_offset_x = cx * step;
6000 g_em->dst_offset_y = cy * step;
6003 else /* tile where movement ends */
6005 if (dx < 0 || dy < 0)
6007 g_em->dst_offset_x = cx * step;
6008 g_em->dst_offset_y = cy * step;
6012 g_em->src_offset_x = cx * step;
6013 g_em->src_offset_y = cy * step;
6017 g_em->width = TILEX - cx * step;
6018 g_em->height = TILEY - cy * step;
6021 /* create unique graphic identifier to decide if tile must be redrawn */
6022 /* bit 31 - 16 (16 bit): EM style element
6023 bit 15 - 12 ( 4 bit): EM style frame
6024 bit 11 - 6 ( 6 bit): graphic width
6025 bit 5 - 0 ( 6 bit): graphic height */
6026 g_em->unique_identifier =
6027 (i << 16) | (j << 12) | (g_em->width << 6) | g_em->height;
6032 /* skip check for EMC elements not contained in original EMC artwork */
6033 if (element == EL_EMC_FAKE_ACID)
6037 if (g_em->bitmap != debug_bitmap ||
6038 g_em->src_x != debug_src_x ||
6039 g_em->src_y != debug_src_y ||
6040 g_em->src_offset_x != 0 ||
6041 g_em->src_offset_y != 0 ||
6042 g_em->dst_offset_x != 0 ||
6043 g_em->dst_offset_y != 0 ||
6044 g_em->width != TILEX ||
6045 g_em->height != TILEY)
6047 static int last_i = -1;
6055 printf("::: EMC GFX ERROR for element %d -> %d ('%s', '%s', %d)",
6056 i, element, element_info[element].token_name,
6057 element_action_info[effective_action].suffix, direction);
6059 if (element != effective_element)
6060 printf(" [%d ('%s')]",
6062 element_info[effective_element].token_name);
6066 if (g_em->bitmap != debug_bitmap)
6067 printf(" %d (%d): different bitmap! (0x%08x != 0x%08x)\n",
6068 j, is_backside, (int)(g_em->bitmap), (int)(debug_bitmap));
6070 if (g_em->src_x != debug_src_x ||
6071 g_em->src_y != debug_src_y)
6072 printf(" frame %d (%c): %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
6073 j, (is_backside ? 'B' : 'F'),
6074 g_em->src_x, g_em->src_y,
6075 g_em->src_x / 32, g_em->src_y / 32,
6076 debug_src_x, debug_src_y,
6077 debug_src_x / 32, debug_src_y / 32);
6079 if (g_em->src_offset_x != 0 ||
6080 g_em->src_offset_y != 0 ||
6081 g_em->dst_offset_x != 0 ||
6082 g_em->dst_offset_y != 0)
6083 printf(" %d (%d): offsets %d,%d and %d,%d should be all 0\n",
6085 g_em->src_offset_x, g_em->src_offset_y,
6086 g_em->dst_offset_x, g_em->dst_offset_y);
6088 if (g_em->width != TILEX ||
6089 g_em->height != TILEY)
6090 printf(" %d (%d): size %d,%d should be %d,%d\n",
6092 g_em->width, g_em->height, TILEX, TILEY);
6099 for (i = 0; i < TILE_MAX; i++)
6101 for (j = 0; j < 8; j++)
6103 int element = object_mapping[i].element_rnd;
6104 int action = object_mapping[i].action;
6106 if (action == ACTION_SMASHED_BY_ROCK &&
6107 element_info[element].graphic[action] ==
6108 element_info[element].graphic[ACTION_DEFAULT])
6110 /* no separate animation for "smashed by rock" -- use rock instead */
6111 struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
6112 struct GraphicInfo_EM *g_xx = &graphic_info_em_object[Ystone_s][7 - j];
6114 g_em->bitmap = g_xx->bitmap;
6115 g_em->src_x = g_xx->src_x;
6116 g_em->src_y = g_xx->src_y;
6117 g_em->src_offset_x = g_xx->src_offset_x;
6118 g_em->src_offset_y = g_xx->src_offset_y;
6119 g_em->dst_offset_x = g_xx->dst_offset_x;
6120 g_em->dst_offset_y = g_xx->dst_offset_y;
6121 g_em->width = g_xx->width;
6122 g_em->height = g_xx->height;
6124 g_em->preserve_background = TRUE;
6129 for (p = 0; p < 2; p++)
6131 for (i = 0; i < SPR_MAX; i++)
6133 int element = player_mapping[p][i].element_rnd;
6134 int action = player_mapping[p][i].action;
6135 int direction = player_mapping[p][i].direction;
6137 for (j = 0; j < 8; j++)
6139 int effective_element = element;
6140 int effective_action = action;
6141 int graphic = (direction == MV_NONE ?
6142 el_act2img(effective_element, effective_action) :
6143 el_act_dir2img(effective_element, effective_action,
6145 struct GraphicInfo *g = &graphic_info[graphic];
6146 struct GraphicInfo_EM *g_em = &graphic_info_em_player[p][i][7 - j];
6152 Bitmap *debug_bitmap = g_em->bitmap;
6153 int debug_src_x = g_em->src_x;
6154 int debug_src_y = g_em->src_y;
6157 int frame = getAnimationFrame(g->anim_frames,
6160 g->anim_start_frame,
6163 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x,&src_y, FALSE);
6165 g_em->bitmap = src_bitmap;
6166 g_em->src_x = src_x;
6167 g_em->src_y = src_y;
6168 g_em->src_offset_x = 0;
6169 g_em->src_offset_y = 0;
6170 g_em->dst_offset_x = 0;
6171 g_em->dst_offset_y = 0;
6172 g_em->width = TILEX;
6173 g_em->height = TILEY;
6176 if (g_em->bitmap != debug_bitmap ||
6177 g_em->src_x != debug_src_x ||
6178 g_em->src_y != debug_src_y)
6180 static int last_i = -1;
6188 printf("::: EMC GFX ERROR for p/a %d/%d -> %d ('%s', '%s', %d)",
6189 p, i, element, element_info[element].token_name,
6190 element_action_info[effective_action].suffix, direction);
6192 if (element != effective_element)
6193 printf(" [%d ('%s')]",
6195 element_info[effective_element].token_name);
6199 if (g_em->bitmap != debug_bitmap)
6200 printf(" %d: different bitmap! (0x%08x != 0x%08x)\n",
6201 j, (int)(g_em->bitmap), (int)(debug_bitmap));
6203 if (g_em->src_x != debug_src_x ||
6204 g_em->src_y != debug_src_y)
6205 printf(" frame %d: %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
6207 g_em->src_x, g_em->src_y,
6208 g_em->src_x / 32, g_em->src_y / 32,
6209 debug_src_x, debug_src_y,
6210 debug_src_x / 32, debug_src_y / 32);