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;
740 boolean draw_start_tile = (cut_mode != CUT_ABOVE); /* only for falling! */
741 boolean draw_end_tile = (cut_mode != CUT_BELOW); /* only for falling! */
743 /* re-calculate animation frame for two-tile movement animation */
744 frame = getGraphicAnimationFrame(graphic, sync_frame);
746 /* check if movement start graphic inside screen area and should be drawn */
747 if (draw_start_tile && IN_SCR_FIELD(x1, y1))
749 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, TRUE);
751 dst_x = FX + x1 * TILEX;
752 dst_y = FY + y1 * TILEY;
754 if (mask_mode == USE_MASKING)
756 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
757 dst_x - src_x, dst_y - src_y);
758 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
762 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
765 MarkTileDirty(x1, y1);
768 /* check if movement end graphic inside screen area and should be drawn */
769 if (draw_end_tile && IN_SCR_FIELD(x2, y2))
771 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, FALSE);
773 dst_x = FX + x2 * TILEX;
774 dst_y = FY + y2 * TILEY;
776 if (mask_mode == USE_MASKING)
778 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
779 dst_x - src_x, dst_y - src_y);
780 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
784 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
787 MarkTileDirty(x2, y2);
791 static void DrawGraphicShifted(int x, int y, int dx, int dy,
792 int graphic, int frame,
793 int cut_mode, int mask_mode)
797 DrawGraphic(x, y, graphic, frame);
802 if (graphic_info[graphic].double_movement) /* EM style movement images */
803 DrawGraphicShiftedDouble(x, y, dx, dy, graphic, frame, cut_mode,mask_mode);
805 DrawGraphicShiftedNormal(x, y, dx, dy, graphic, frame, cut_mode,mask_mode);
808 void DrawGraphicShiftedThruMask(int x, int y, int dx, int dy, int graphic,
809 int frame, int cut_mode)
811 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, USE_MASKING);
814 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
815 int cut_mode, int mask_mode)
817 int lx = LEVELX(x), ly = LEVELY(y);
821 if (IN_LEV_FIELD(lx, ly))
823 SetRandomAnimationValue(lx, ly);
825 graphic = el_act_dir2img(element, GfxAction[lx][ly], GfxDir[lx][ly]);
826 frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
828 /* do not use double (EM style) movement graphic when not moving */
829 if (graphic_info[graphic].double_movement && !dx && !dy)
831 graphic = el_act_dir2img(element, ACTION_DEFAULT, GfxDir[lx][ly]);
832 frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
835 else /* border element */
837 graphic = el2img(element);
838 frame = getGraphicAnimationFrame(graphic, -1);
841 if (element == EL_EXPANDABLE_WALL)
843 boolean left_stopped = FALSE, right_stopped = FALSE;
845 if (!IN_LEV_FIELD(lx - 1, ly) || IS_WALL(Feld[lx - 1][ly]))
847 if (!IN_LEV_FIELD(lx + 1, ly) || IS_WALL(Feld[lx + 1][ly]))
848 right_stopped = TRUE;
850 if (left_stopped && right_stopped)
852 else if (left_stopped)
854 graphic = IMG_EXPANDABLE_WALL_GROWING_RIGHT;
855 frame = graphic_info[graphic].anim_frames - 1;
857 else if (right_stopped)
859 graphic = IMG_EXPANDABLE_WALL_GROWING_LEFT;
860 frame = graphic_info[graphic].anim_frames - 1;
865 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
866 else if (mask_mode == USE_MASKING)
867 DrawGraphicThruMask(x, y, graphic, frame);
869 DrawGraphic(x, y, graphic, frame);
872 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
873 int cut_mode, int mask_mode)
875 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
876 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
877 cut_mode, mask_mode);
880 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
883 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
886 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
889 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
892 void DrawLevelElementThruMask(int x, int y, int element)
894 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
897 void DrawLevelFieldThruMask(int x, int y)
899 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
902 #define TILE_GFX_ELEMENT(x, y) \
903 (GfxElement[x][y] != EL_UNDEFINED && Feld[x][y] != EL_EXPLOSION ? \
904 GfxElement[x][y] : Feld[x][y])
906 static void DrawLevelFieldCrumbledSandExt(int x, int y, int graphic, int frame)
910 int sx = SCREENX(x), sy = SCREENY(y);
912 int width, height, cx, cy, i;
913 int crumbled_border_size = graphic_info[graphic].border_size;
914 static int xy[4][2] =
922 if (!IN_LEV_FIELD(x, y))
925 element = TILE_GFX_ELEMENT(x, y);
927 /* crumble field itself */
928 if (GFX_CRUMBLED(element) && !IS_MOVING(x, y))
930 if (!IN_SCR_FIELD(sx, sy))
933 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
935 for (i = 0; i < 4; i++)
937 int xx = x + xy[i][0];
938 int yy = y + xy[i][1];
940 element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
943 /* check if neighbour field is of same type */
944 if (GFX_CRUMBLED(element) && !IS_MOVING(xx, yy))
947 if (i == 1 || i == 2)
949 width = crumbled_border_size;
951 cx = (i == 2 ? TILEX - crumbled_border_size : 0);
957 height = crumbled_border_size;
959 cy = (i == 3 ? TILEY - crumbled_border_size : 0);
962 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
963 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
966 MarkTileDirty(sx, sy);
968 else /* crumble neighbour fields */
970 for (i = 0; i < 4; i++)
972 int xx = x + xy[i][0];
973 int yy = y + xy[i][1];
974 int sxx = sx + xy[i][0];
975 int syy = sy + xy[i][1];
978 if (!IN_LEV_FIELD(xx, yy) ||
979 !IN_SCR_FIELD(sxx, syy) ||
984 if (Feld[xx][yy] == EL_ELEMENT_SNAPPING)
988 element = TILE_GFX_ELEMENT(xx, yy);
990 if (!GFX_CRUMBLED(element))
993 if (!IN_LEV_FIELD(xx, yy) ||
994 !IN_SCR_FIELD(sxx, syy) ||
995 !GFX_CRUMBLED(Feld[xx][yy]) ||
1001 graphic = el_act2crm(element, ACTION_DEFAULT);
1003 graphic = el_act2crm(Feld[xx][yy], ACTION_DEFAULT);
1005 crumbled_border_size = graphic_info[graphic].border_size;
1007 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1009 if (i == 1 || i == 2)
1011 width = crumbled_border_size;
1013 cx = (i == 1 ? TILEX - crumbled_border_size : 0);
1019 height = crumbled_border_size;
1021 cy = (i == 0 ? TILEY - crumbled_border_size : 0);
1024 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1025 width, height, FX + sxx * TILEX + cx, FY + syy * TILEY + cy);
1027 MarkTileDirty(sxx, syy);
1032 void DrawLevelFieldCrumbledSand(int x, int y)
1036 if (!IN_LEV_FIELD(x, y))
1040 if (Feld[x][y] == EL_ELEMENT_SNAPPING &&
1041 GFX_CRUMBLED(GfxElement[x][y]))
1043 DrawLevelFieldCrumbledSandDigging(x, y, GfxDir[x][y], GfxFrame[x][y]);
1049 graphic = el_act2crm(TILE_GFX_ELEMENT(x, y), ACTION_DEFAULT);
1051 graphic = el_act2crm(Feld[x][y], ACTION_DEFAULT);
1054 DrawLevelFieldCrumbledSandExt(x, y, graphic, 0);
1057 void DrawLevelFieldCrumbledSandDigging(int x, int y, int direction,
1060 int graphic1 = el_act_dir2img(GfxElement[x][y], ACTION_DIGGING, direction);
1061 int graphic2 = el_act_dir2crm(GfxElement[x][y], ACTION_DIGGING, direction);
1062 int frame1 = getGraphicAnimationFrame(graphic1, step_frame);
1063 int frame2 = getGraphicAnimationFrame(graphic2, step_frame);
1064 int sx = SCREENX(x), sy = SCREENY(y);
1066 DrawGraphic(sx, sy, graphic1, frame1);
1067 DrawLevelFieldCrumbledSandExt(x, y, graphic2, frame2);
1070 void DrawLevelFieldCrumbledSandNeighbours(int x, int y)
1072 int sx = SCREENX(x), sy = SCREENY(y);
1073 static int xy[4][2] =
1082 for (i = 0; i < 4; i++)
1084 int xx = x + xy[i][0];
1085 int yy = y + xy[i][1];
1086 int sxx = sx + xy[i][0];
1087 int syy = sy + xy[i][1];
1089 if (!IN_LEV_FIELD(xx, yy) ||
1090 !IN_SCR_FIELD(sxx, syy) ||
1091 !GFX_CRUMBLED(Feld[xx][yy]) ||
1095 DrawLevelField(xx, yy);
1099 static int getBorderElement(int x, int y)
1103 { EL_STEELWALL_TOPLEFT, EL_INVISIBLE_STEELWALL_TOPLEFT },
1104 { EL_STEELWALL_TOPRIGHT, EL_INVISIBLE_STEELWALL_TOPRIGHT },
1105 { EL_STEELWALL_BOTTOMLEFT, EL_INVISIBLE_STEELWALL_BOTTOMLEFT },
1106 { EL_STEELWALL_BOTTOMRIGHT, EL_INVISIBLE_STEELWALL_BOTTOMRIGHT },
1107 { EL_STEELWALL_VERTICAL, EL_INVISIBLE_STEELWALL_VERTICAL },
1108 { EL_STEELWALL_HORIZONTAL, EL_INVISIBLE_STEELWALL_HORIZONTAL },
1109 { EL_STEELWALL, EL_INVISIBLE_STEELWALL }
1111 int steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
1112 int steel_position = (x == -1 && y == -1 ? 0 :
1113 x == lev_fieldx && y == -1 ? 1 :
1114 x == -1 && y == lev_fieldy ? 2 :
1115 x == lev_fieldx && y == lev_fieldy ? 3 :
1116 x == -1 || x == lev_fieldx ? 4 :
1117 y == -1 || y == lev_fieldy ? 5 : 6);
1119 return border[steel_position][steel_type];
1122 void DrawScreenElement(int x, int y, int element)
1124 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1125 DrawLevelFieldCrumbledSand(LEVELX(x), LEVELY(y));
1128 void DrawLevelElement(int x, int y, int element)
1130 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1131 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1134 void DrawScreenField(int x, int y)
1136 int lx = LEVELX(x), ly = LEVELY(y);
1137 int element, content;
1139 if (!IN_LEV_FIELD(lx, ly))
1141 if (lx < -1 || lx > lev_fieldx || ly < -1 || ly > lev_fieldy)
1144 element = getBorderElement(lx, ly);
1146 DrawScreenElement(x, y, element);
1150 element = Feld[lx][ly];
1151 content = Store[lx][ly];
1153 if (IS_MOVING(lx, ly))
1155 int horiz_move = (MovDir[lx][ly] == MV_LEFT || MovDir[lx][ly] == MV_RIGHT);
1156 boolean cut_mode = NO_CUTTING;
1158 if (element == EL_QUICKSAND_EMPTYING ||
1159 element == EL_MAGIC_WALL_EMPTYING ||
1160 element == EL_BD_MAGIC_WALL_EMPTYING ||
1161 element == EL_AMOEBA_DROPPING)
1162 cut_mode = CUT_ABOVE;
1163 else if (element == EL_QUICKSAND_FILLING ||
1164 element == EL_MAGIC_WALL_FILLING ||
1165 element == EL_BD_MAGIC_WALL_FILLING)
1166 cut_mode = CUT_BELOW;
1168 if (cut_mode == CUT_ABOVE)
1169 DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1171 DrawScreenElement(x, y, EL_EMPTY);
1174 DrawScreenElementShifted(x, y, MovPos[lx][ly], 0, element, NO_CUTTING);
1175 else if (cut_mode == NO_CUTTING)
1176 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], element, cut_mode);
1178 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], content, cut_mode);
1180 if (content == EL_ACID)
1182 int dir = MovDir[lx][ly];
1183 int newlx = lx + (dir == MV_LEFT ? -1 : dir == MV_RIGHT ? +1 : 0);
1184 int newly = ly + (dir == MV_UP ? -1 : dir == MV_DOWN ? +1 : 0);
1186 DrawLevelElementThruMask(newlx, newly, EL_ACID);
1189 else if (IS_BLOCKED(lx, ly))
1194 boolean cut_mode = NO_CUTTING;
1195 int element_old, content_old;
1197 Blocked2Moving(lx, ly, &oldx, &oldy);
1200 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1201 MovDir[oldx][oldy] == MV_RIGHT);
1203 element_old = Feld[oldx][oldy];
1204 content_old = Store[oldx][oldy];
1206 if (element_old == EL_QUICKSAND_EMPTYING ||
1207 element_old == EL_MAGIC_WALL_EMPTYING ||
1208 element_old == EL_BD_MAGIC_WALL_EMPTYING ||
1209 element_old == EL_AMOEBA_DROPPING)
1210 cut_mode = CUT_ABOVE;
1212 DrawScreenElement(x, y, EL_EMPTY);
1215 DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
1217 else if (cut_mode == NO_CUTTING)
1218 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
1221 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
1224 else if (IS_DRAWABLE(element))
1225 DrawScreenElement(x, y, element);
1227 DrawScreenElement(x, y, EL_EMPTY);
1230 void DrawLevelField(int x, int y)
1232 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1233 DrawScreenField(SCREENX(x), SCREENY(y));
1234 else if (IS_MOVING(x, y))
1238 Moving2Blocked(x, y, &newx, &newy);
1239 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1240 DrawScreenField(SCREENX(newx), SCREENY(newy));
1242 else if (IS_BLOCKED(x, y))
1246 Blocked2Moving(x, y, &oldx, &oldy);
1247 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1248 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1252 void DrawMiniElement(int x, int y, int element)
1256 graphic = el2edimg(element);
1257 DrawMiniGraphic(x, y, graphic);
1260 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1262 int x = sx + scroll_x, y = sy + scroll_y;
1264 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1265 DrawMiniElement(sx, sy, EL_EMPTY);
1266 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1267 DrawMiniElement(sx, sy, Feld[x][y]);
1269 DrawMiniGraphic(sx, sy, el2edimg(getBorderElement(x, y)));
1272 void DrawEnvelopeBackground(int envelope_nr, int startx, int starty,
1273 int x, int y, int xsize, int ysize, int font_nr)
1275 int font_width = getFontWidth(font_nr);
1276 int font_height = getFontHeight(font_nr);
1277 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1280 int dst_x = SX + startx + x * font_width;
1281 int dst_y = SY + starty + y * font_height;
1282 int width = graphic_info[graphic].width;
1283 int height = graphic_info[graphic].height;
1284 int inner_width = MAX(width - 2 * font_width, font_width);
1285 int inner_height = MAX(height - 2 * font_height, font_height);
1286 int inner_sx = (width >= 3 * font_width ? font_width : 0);
1287 int inner_sy = (height >= 3 * font_height ? font_height : 0);
1288 boolean draw_masked = graphic_info[graphic].draw_masked;
1290 getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
1292 if (src_bitmap == NULL || width < font_width || height < font_height)
1294 ClearRectangle(drawto, dst_x, dst_y, font_width, font_height);
1298 src_x += (x == 0 ? 0 : x == xsize - 1 ? width - font_width :
1299 inner_sx + (x - 1) * font_width % inner_width);
1300 src_y += (y == 0 ? 0 : y == ysize - 1 ? height - font_height :
1301 inner_sy + (y - 1) * font_height % inner_height);
1305 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1306 dst_x - src_x, dst_y - src_y);
1307 BlitBitmapMasked(src_bitmap, drawto, src_x, src_y, font_width, font_height,
1311 BlitBitmap(src_bitmap, drawto, src_x, src_y, font_width, font_height,
1315 void AnimateEnvelope(int envelope_nr, int anim_mode, int action)
1317 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1318 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
1319 int mask_mode = (src_bitmap != NULL ? BLIT_MASKED : BLIT_ON_BACKGROUND);
1320 boolean ffwd_delay = (tape.playing && tape.fast_forward);
1321 boolean no_delay = (tape.warp_forward);
1322 unsigned long anim_delay = 0;
1323 int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
1324 int anim_delay_value = (no_delay ? 0 : frame_delay_value);
1325 int font_nr = FONT_ENVELOPE_1 + envelope_nr;
1326 int font_width = getFontWidth(font_nr);
1327 int font_height = getFontHeight(font_nr);
1328 int max_xsize = level.envelope_xsize[envelope_nr];
1329 int max_ysize = level.envelope_ysize[envelope_nr];
1330 int xstart = (anim_mode & ANIM_VERTICAL ? max_xsize : 0);
1331 int ystart = (anim_mode & ANIM_HORIZONTAL ? max_ysize : 0);
1332 int xend = max_xsize;
1333 int yend = (anim_mode != ANIM_DEFAULT ? max_ysize : 0);
1334 int xstep = (xstart < xend ? 1 : 0);
1335 int ystep = (ystart < yend || xstep == 0 ? 1 : 0);
1338 for (x = xstart, y = ystart; x <= xend && y <= yend; x += xstep, y += ystep)
1340 int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2;
1341 int ysize = (action == ACTION_CLOSING ? yend - (y - ystart) : y) + 2;
1342 int sx = (SXSIZE - xsize * font_width) / 2;
1343 int sy = (SYSIZE - ysize * font_height) / 2;
1346 SetDrawtoField(DRAW_BUFFERED);
1348 BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
1350 SetDrawtoField(DRAW_BACKBUFFER);
1352 for (yy = 0; yy < ysize; yy++) for (xx = 0; xx < xsize; xx++)
1353 DrawEnvelopeBackground(envelope_nr, sx,sy, xx,yy, xsize, ysize, font_nr);
1355 DrawTextToTextArea(SX + sx + font_width, SY + sy + font_height,
1356 level.envelope_text[envelope_nr], font_nr, max_xsize,
1357 xsize - 2, ysize - 2, mask_mode);
1359 redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
1362 WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
1366 void ShowEnvelope(int envelope_nr)
1368 int element = EL_ENVELOPE_1 + envelope_nr;
1369 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1370 int sound_opening = element_info[element].sound[ACTION_OPENING];
1371 int sound_closing = element_info[element].sound[ACTION_CLOSING];
1372 boolean ffwd_delay = (tape.playing && tape.fast_forward);
1373 boolean no_delay = (tape.warp_forward);
1374 int normal_delay_value = ONE_SECOND_DELAY / (ffwd_delay ? 2 : 1);
1375 int wait_delay_value = (no_delay ? 0 : normal_delay_value);
1376 int anim_mode = graphic_info[graphic].anim_mode;
1377 int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL:
1378 anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode);
1380 game.envelope_active = TRUE; /* needed for RedrawPlayfield() events */
1382 PlaySoundStereo(sound_opening, SOUND_MIDDLE);
1384 if (anim_mode == ANIM_DEFAULT)
1385 AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_OPENING);
1387 AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_OPENING);
1390 Delay(wait_delay_value);
1392 WaitForEventToContinue();
1394 PlaySoundStereo(sound_closing, SOUND_MIDDLE);
1396 if (anim_mode != ANIM_NONE)
1397 AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_CLOSING);
1399 if (anim_mode == ANIM_DEFAULT)
1400 AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_CLOSING);
1402 game.envelope_active = FALSE;
1404 SetDrawtoField(DRAW_BUFFERED);
1406 redraw_mask |= REDRAW_FIELD;
1410 void getMicroGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1412 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
1413 int mini_startx = src_bitmap->width * 3 / 4;
1414 int mini_starty = src_bitmap->height * 2 / 3;
1415 int src_x = mini_startx + graphic_info[graphic].src_x / 8;
1416 int src_y = mini_starty + graphic_info[graphic].src_y / 8;
1418 *bitmap = src_bitmap;
1423 void DrawMicroElement(int xpos, int ypos, int element)
1427 int graphic = el2preimg(element);
1429 getMicroGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1430 BlitBitmap(src_bitmap, drawto, src_x, src_y, MICRO_TILEX, MICRO_TILEY,
1438 SetDrawBackgroundMask(REDRAW_NONE);
1441 for (x = BX1; x <= BX2; x++)
1442 for (y = BY1; y <= BY2; y++)
1443 DrawScreenField(x, y);
1445 redraw_mask |= REDRAW_FIELD;
1448 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1452 for (x = 0; x < size_x; x++)
1453 for (y = 0; y < size_y; y++)
1454 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1456 redraw_mask |= REDRAW_FIELD;
1459 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1463 DrawBackground(xpos, ypos, MICROLEVEL_XSIZE, MICROLEVEL_YSIZE);
1465 if (lev_fieldx < STD_LEV_FIELDX)
1466 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1467 if (lev_fieldy < STD_LEV_FIELDY)
1468 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1470 xpos += MICRO_TILEX;
1471 ypos += MICRO_TILEY;
1473 for (x = -1; x <= STD_LEV_FIELDX; x++)
1475 for (y = -1; y <= STD_LEV_FIELDY; y++)
1477 int lx = from_x + x, ly = from_y + y;
1479 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1480 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1481 level.field[lx][ly]);
1482 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1
1483 && BorderElement != EL_EMPTY)
1484 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1485 getBorderElement(lx, ly));
1489 redraw_mask |= REDRAW_MICROLEVEL;
1492 #define MICROLABEL_EMPTY 0
1493 #define MICROLABEL_LEVEL_NAME 1
1494 #define MICROLABEL_LEVEL_AUTHOR_HEAD 2
1495 #define MICROLABEL_LEVEL_AUTHOR 3
1496 #define MICROLABEL_IMPORTED_FROM_HEAD 4
1497 #define MICROLABEL_IMPORTED_FROM 5
1498 #define MICROLABEL_IMPORTED_BY_HEAD 6
1499 #define MICROLABEL_IMPORTED_BY 7
1501 static void DrawMicroLevelLabelExt(int mode)
1503 char label_text[MAX_OUTPUT_LINESIZE + 1];
1504 int max_len_label_text;
1505 int font_nr = FONT_TEXT_2;
1508 if (mode == MICROLABEL_LEVEL_AUTHOR_HEAD ||
1509 mode == MICROLABEL_IMPORTED_FROM_HEAD ||
1510 mode == MICROLABEL_IMPORTED_BY_HEAD)
1511 font_nr = FONT_TEXT_3;
1513 max_len_label_text = SXSIZE / getFontWidth(font_nr);
1515 for (i = 0; i < max_len_label_text; i++)
1516 label_text[i] = ' ';
1517 label_text[max_len_label_text] = '\0';
1519 if (strlen(label_text) > 0)
1521 int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
1522 int lypos = MICROLABEL2_YPOS;
1524 DrawText(lxpos, lypos, label_text, font_nr);
1528 (mode == MICROLABEL_LEVEL_NAME ? level.name :
1529 mode == MICROLABEL_LEVEL_AUTHOR_HEAD ? "created by" :
1530 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
1531 mode == MICROLABEL_IMPORTED_FROM_HEAD ? "imported from" :
1532 mode == MICROLABEL_IMPORTED_FROM ? leveldir_current->imported_from :
1533 mode == MICROLABEL_IMPORTED_BY_HEAD ? "imported by" :
1534 mode == MICROLABEL_IMPORTED_BY ? leveldir_current->imported_by :""),
1535 max_len_label_text);
1536 label_text[max_len_label_text] = '\0';
1538 if (strlen(label_text) > 0)
1540 int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
1541 int lypos = MICROLABEL2_YPOS;
1543 DrawText(lxpos, lypos, label_text, font_nr);
1546 redraw_mask |= REDRAW_MICROLEVEL;
1549 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1551 static unsigned long scroll_delay = 0;
1552 static unsigned long label_delay = 0;
1553 static int from_x, from_y, scroll_direction;
1554 static int label_state, label_counter;
1555 int last_game_status = game_status; /* save current game status */
1557 /* force PREVIEW font on preview level */
1558 game_status = GAME_MODE_PSEUDO_PREVIEW;
1562 from_x = from_y = 0;
1563 scroll_direction = MV_RIGHT;
1567 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1568 DrawMicroLevelLabelExt(label_state);
1570 /* initialize delay counters */
1571 DelayReached(&scroll_delay, 0);
1572 DelayReached(&label_delay, 0);
1574 if (leveldir_current->name)
1576 char label_text[MAX_OUTPUT_LINESIZE + 1];
1577 int font_nr = FONT_TEXT_1;
1578 int max_len_label_text = SXSIZE / getFontWidth(font_nr);
1581 strncpy(label_text, leveldir_current->name, max_len_label_text);
1582 label_text[max_len_label_text] = '\0';
1584 lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
1585 lypos = SY + MICROLABEL1_YPOS;
1587 DrawText(lxpos, lypos, label_text, font_nr);
1590 game_status = last_game_status; /* restore current game status */
1595 /* scroll micro level, if needed */
1596 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1597 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1599 switch (scroll_direction)
1605 scroll_direction = MV_UP;
1609 if (from_x < lev_fieldx - STD_LEV_FIELDX)
1612 scroll_direction = MV_DOWN;
1619 scroll_direction = MV_RIGHT;
1623 if (from_y < lev_fieldy - STD_LEV_FIELDY)
1626 scroll_direction = MV_LEFT;
1633 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1636 /* !!! THIS ALL SUCKS -- SHOULD BE CLEANLY REWRITTEN !!! */
1637 /* redraw micro level label, if needed */
1638 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1639 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1640 strcmp(level.author, leveldir_current->name) != 0 &&
1641 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1643 int max_label_counter = 23;
1645 if (leveldir_current->imported_from != NULL &&
1646 strlen(leveldir_current->imported_from) > 0)
1647 max_label_counter += 14;
1648 if (leveldir_current->imported_by != NULL &&
1649 strlen(leveldir_current->imported_by) > 0)
1650 max_label_counter += 14;
1652 label_counter = (label_counter + 1) % max_label_counter;
1653 label_state = (label_counter >= 0 && label_counter <= 7 ?
1654 MICROLABEL_LEVEL_NAME :
1655 label_counter >= 9 && label_counter <= 12 ?
1656 MICROLABEL_LEVEL_AUTHOR_HEAD :
1657 label_counter >= 14 && label_counter <= 21 ?
1658 MICROLABEL_LEVEL_AUTHOR :
1659 label_counter >= 23 && label_counter <= 26 ?
1660 MICROLABEL_IMPORTED_FROM_HEAD :
1661 label_counter >= 28 && label_counter <= 35 ?
1662 MICROLABEL_IMPORTED_FROM :
1663 label_counter >= 37 && label_counter <= 40 ?
1664 MICROLABEL_IMPORTED_BY_HEAD :
1665 label_counter >= 42 && label_counter <= 49 ?
1666 MICROLABEL_IMPORTED_BY : MICROLABEL_EMPTY);
1668 if (leveldir_current->imported_from == NULL &&
1669 (label_state == MICROLABEL_IMPORTED_FROM_HEAD ||
1670 label_state == MICROLABEL_IMPORTED_FROM))
1671 label_state = (label_state == MICROLABEL_IMPORTED_FROM_HEAD ?
1672 MICROLABEL_IMPORTED_BY_HEAD : MICROLABEL_IMPORTED_BY);
1674 DrawMicroLevelLabelExt(label_state);
1677 game_status = last_game_status; /* restore current game status */
1680 inline void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
1681 int graphic, int sync_frame, int mask_mode)
1683 int frame = getGraphicAnimationFrame(graphic, sync_frame);
1685 if (mask_mode == USE_MASKING)
1686 DrawGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
1688 DrawGraphicExt(dst_bitmap, x, y, graphic, frame);
1691 inline void DrawGraphicAnimation(int x, int y, int graphic)
1693 int lx = LEVELX(x), ly = LEVELY(y);
1695 if (!IN_SCR_FIELD(x, y))
1698 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
1699 graphic, GfxFrame[lx][ly], NO_MASKING);
1700 MarkTileDirty(x, y);
1703 void DrawLevelGraphicAnimation(int x, int y, int graphic)
1705 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
1708 void DrawLevelElementAnimation(int x, int y, int element)
1710 int graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
1712 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
1715 inline void DrawLevelGraphicAnimationIfNeeded(int x, int y, int graphic)
1717 int sx = SCREENX(x), sy = SCREENY(y);
1719 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
1722 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
1725 DrawGraphicAnimation(sx, sy, graphic);
1728 if (GFX_CRUMBLED(TILE_GFX_ELEMENT(x, y)))
1729 DrawLevelFieldCrumbledSand(x, y);
1731 if (GFX_CRUMBLED(Feld[x][y]))
1732 DrawLevelFieldCrumbledSand(x, y);
1736 void DrawLevelElementAnimationIfNeeded(int x, int y, int element)
1738 int sx = SCREENX(x), sy = SCREENY(y);
1741 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
1744 graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
1746 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
1749 DrawGraphicAnimation(sx, sy, graphic);
1751 if (GFX_CRUMBLED(element))
1752 DrawLevelFieldCrumbledSand(x, y);
1755 static int getPlayerGraphic(struct PlayerInfo *player, int move_dir)
1757 if (player->use_murphy)
1759 /* this works only because currently only one player can be "murphy" ... */
1760 static int last_horizontal_dir = MV_LEFT;
1761 int graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, move_dir);
1763 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
1764 last_horizontal_dir = move_dir;
1766 if (graphic == IMG_SP_MURPHY) /* undefined => use special graphic */
1768 int direction = (player->is_snapping ? move_dir : last_horizontal_dir);
1770 graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, direction);
1776 return el_act_dir2img(player->artwork_element, player->GfxAction,move_dir);
1779 static boolean equalGraphics(int graphic1, int graphic2)
1781 struct GraphicInfo *g1 = &graphic_info[graphic1];
1782 struct GraphicInfo *g2 = &graphic_info[graphic2];
1784 return (g1->bitmap == g2->bitmap &&
1785 g1->src_x == g2->src_x &&
1786 g1->src_y == g2->src_y &&
1787 g1->anim_frames == g2->anim_frames &&
1788 g1->anim_delay == g2->anim_delay &&
1789 g1->anim_mode == g2->anim_mode);
1792 void DrawAllPlayers()
1796 for (i = 0; i < MAX_PLAYERS; i++)
1797 if (stored_player[i].active)
1798 DrawPlayer(&stored_player[i]);
1801 void DrawPlayerField(int x, int y)
1803 if (!IS_PLAYER(x, y))
1806 DrawPlayer(PLAYERINFO(x, y));
1809 void DrawPlayer(struct PlayerInfo *player)
1811 int jx = player->jx;
1812 int jy = player->jy;
1813 int move_dir = player->MovDir;
1814 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? +1 : 0);
1815 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? +1 : 0);
1816 int last_jx = (player->is_moving ? jx - dx : jx);
1817 int last_jy = (player->is_moving ? jy - dy : jy);
1818 int next_jx = jx + dx;
1819 int next_jy = jy + dy;
1820 boolean player_is_moving = (player->MovPos ? TRUE : FALSE);
1821 int sx = SCREENX(jx), sy = SCREENY(jy);
1822 int sxx = 0, syy = 0;
1823 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
1825 int action = ACTION_DEFAULT;
1826 int last_player_graphic = getPlayerGraphic(player, move_dir);
1827 int last_player_frame = player->Frame;
1830 if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
1834 if (!IN_LEV_FIELD(jx, jy))
1836 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
1837 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
1838 printf("DrawPlayerField(): This should never happen!\n");
1843 if (element == EL_EXPLOSION)
1846 action = (player->is_pushing ? ACTION_PUSHING :
1847 player->is_digging ? ACTION_DIGGING :
1848 player->is_collecting ? ACTION_COLLECTING :
1849 player->is_moving ? ACTION_MOVING :
1850 player->is_snapping ? ACTION_SNAPPING :
1851 player->is_dropping ? ACTION_DROPPING :
1852 player->is_waiting ? player->action_waiting : ACTION_DEFAULT);
1854 InitPlayerGfxAnimation(player, action, move_dir);
1856 /* ----------------------------------------------------------------------- */
1857 /* draw things in the field the player is leaving, if needed */
1858 /* ----------------------------------------------------------------------- */
1860 if (player->is_moving)
1862 if (Back[last_jx][last_jy] && IS_DRAWABLE(last_element))
1864 DrawLevelElement(last_jx, last_jy, Back[last_jx][last_jy]);
1866 if (last_element == EL_DYNAMITE_ACTIVE ||
1867 last_element == EL_EM_DYNAMITE_ACTIVE ||
1868 last_element == EL_SP_DISK_RED_ACTIVE)
1869 DrawDynamite(last_jx, last_jy);
1871 DrawLevelFieldThruMask(last_jx, last_jy);
1873 else if (last_element == EL_DYNAMITE_ACTIVE ||
1874 last_element == EL_EM_DYNAMITE_ACTIVE ||
1875 last_element == EL_SP_DISK_RED_ACTIVE)
1876 DrawDynamite(last_jx, last_jy);
1878 DrawLevelField(last_jx, last_jy);
1880 if (player->is_pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
1881 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
1884 if (!IN_SCR_FIELD(sx, sy))
1887 if (setup.direct_draw)
1888 SetDrawtoField(DRAW_BUFFERED);
1890 /* ----------------------------------------------------------------------- */
1891 /* draw things behind the player, if needed */
1892 /* ----------------------------------------------------------------------- */
1895 DrawLevelElement(jx, jy, Back[jx][jy]);
1896 else if (IS_ACTIVE_BOMB(element))
1897 DrawLevelElement(jx, jy, EL_EMPTY);
1900 if (player_is_moving && GfxElement[jx][jy] != EL_UNDEFINED)
1902 if (GFX_CRUMBLED(GfxElement[jx][jy]))
1903 DrawLevelFieldCrumbledSandDigging(jx, jy, move_dir, player->StepFrame);
1906 int old_element = GfxElement[jx][jy];
1907 int old_graphic = el_act_dir2img(old_element, action, move_dir);
1908 int frame = getGraphicAnimationFrame(old_graphic, player->StepFrame);
1910 DrawGraphic(sx, sy, old_graphic, frame);
1915 GfxElement[jx][jy] = EL_UNDEFINED;
1917 /* make sure that pushed elements are drawn with correct frame rate */
1918 if (player->is_pushing && player->is_moving)
1919 GfxFrame[jx][jy] = player->StepFrame;
1921 DrawLevelField(jx, jy);
1925 /* ----------------------------------------------------------------------- */
1926 /* draw player himself */
1927 /* ----------------------------------------------------------------------- */
1929 graphic = getPlayerGraphic(player, move_dir);
1931 /* in the case of changed player action or direction, prevent the current
1932 animation frame from being restarted for identical animations */
1933 if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic))
1934 player->Frame = last_player_frame;
1936 frame = getGraphicAnimationFrame(graphic, player->Frame);
1940 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
1941 sxx = player->GfxPos;
1943 syy = player->GfxPos;
1946 if (!setup.soft_scrolling && ScreenMovPos)
1949 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
1951 if (SHIELD_ON(player))
1953 int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
1954 IMG_SHIELD_NORMAL_ACTIVE);
1955 int frame = getGraphicAnimationFrame(graphic, -1);
1957 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
1960 /* ----------------------------------------------------------------------- */
1961 /* draw things the player is pushing, if needed */
1962 /* ----------------------------------------------------------------------- */
1965 printf("::: %d, %d [%d, %d] [%d]\n",
1966 player->is_pushing, player_is_moving, player->GfxAction,
1967 player->is_moving, player_is_moving);
1971 if (player->is_pushing && player->is_moving)
1973 int px = SCREENX(jx), py = SCREENY(jy);
1974 int pxx = (TILEX - ABS(sxx)) * dx;
1975 int pyy = (TILEY - ABS(syy)) * dy;
1980 if (!IS_MOVING(jx, jy)) /* push movement already finished */
1981 element = Feld[next_jx][next_jy];
1983 graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
1984 frame = getGraphicAnimationFrame(graphic, player->StepFrame);
1986 /* draw background element under pushed element (like the Sokoban field) */
1987 if (Back[next_jx][next_jy])
1988 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
1990 /* masked drawing is needed for EMC style (double) movement graphics */
1991 DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame, NO_CUTTING);
1995 /* ----------------------------------------------------------------------- */
1996 /* draw things in front of player (active dynamite or dynabombs) */
1997 /* ----------------------------------------------------------------------- */
1999 if (IS_ACTIVE_BOMB(element))
2001 graphic = el2img(element);
2002 frame = getGraphicAnimationFrame(graphic, GfxFrame[jx][jy]);
2004 if (game.emulation == EMU_SUPAPLEX)
2005 DrawGraphic(sx, sy, IMG_SP_DISK_RED, frame);
2007 DrawGraphicThruMask(sx, sy, graphic, frame);
2010 if (player_is_moving && last_element == EL_EXPLOSION)
2012 int graphic = el_act2img(GfxElement[last_jx][last_jy], ACTION_EXPLODING);
2013 int delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2);
2014 int phase = ExplodePhase[last_jx][last_jy] - 1;
2015 int frame = getGraphicAnimationFrame(graphic, phase - delay);
2018 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy), graphic, frame);
2021 /* ----------------------------------------------------------------------- */
2022 /* draw elements the player is just walking/passing through/under */
2023 /* ----------------------------------------------------------------------- */
2025 if (player_is_moving)
2027 /* handle the field the player is leaving ... */
2028 if (IS_ACCESSIBLE_INSIDE(last_element))
2029 DrawLevelField(last_jx, last_jy);
2030 else if (IS_ACCESSIBLE_UNDER(last_element))
2031 DrawLevelFieldThruMask(last_jx, last_jy);
2034 /* do not redraw accessible elements if the player is just pushing them */
2035 if (!player_is_moving || !player->is_pushing)
2037 /* ... and the field the player is entering */
2038 if (IS_ACCESSIBLE_INSIDE(element))
2039 DrawLevelField(jx, jy);
2040 else if (IS_ACCESSIBLE_UNDER(element))
2041 DrawLevelFieldThruMask(jx, jy);
2044 if (setup.direct_draw)
2046 int dst_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
2047 int dst_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
2048 int x_size = TILEX * (1 + ABS(jx - last_jx));
2049 int y_size = TILEY * (1 + ABS(jy - last_jy));
2051 BlitBitmap(drawto_field, window,
2052 dst_x, dst_y, x_size, y_size, dst_x, dst_y);
2053 SetDrawtoField(DRAW_DIRECT);
2056 MarkTileDirty(sx, sy);
2059 /* ------------------------------------------------------------------------- */
2061 void WaitForEventToContinue()
2063 boolean still_wait = TRUE;
2065 /* simulate releasing mouse button over last gadget, if still pressed */
2067 HandleGadgets(-1, -1, 0);
2069 button_status = MB_RELEASED;
2081 case EVENT_BUTTONPRESS:
2082 case EVENT_KEYPRESS:
2086 case EVENT_KEYRELEASE:
2087 ClearPlayerAction();
2091 HandleOtherEvents(&event);
2095 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2102 /* don't eat all CPU time */
2107 #define MAX_REQUEST_LINES 13
2108 #define MAX_REQUEST_LINE_FONT1_LEN 7
2109 #define MAX_REQUEST_LINE_FONT2_LEN 10
2111 boolean Request(char *text, unsigned int req_state)
2113 int mx, my, ty, result = -1;
2114 unsigned int old_door_state;
2115 int last_game_status = game_status; /* save current game status */
2116 int max_request_line_len = MAX_REQUEST_LINE_FONT1_LEN;
2117 int font_nr = FONT_TEXT_2;
2118 int max_word_len = 0;
2121 for (text_ptr = text; *text_ptr; text_ptr++)
2123 max_word_len = (*text_ptr != ' ' ? max_word_len + 1 : 0);
2125 if (max_word_len > MAX_REQUEST_LINE_FONT1_LEN)
2127 max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
2128 font_nr = FONT_LEVEL_NUMBER;
2134 if (game_status == GAME_MODE_PLAYING &&
2135 level.game_engine_type == GAME_ENGINE_TYPE_EM)
2136 BlitScreenToBitmap_EM(backbuffer);
2138 /* disable deactivated drawing when quick-loading level tape recording */
2139 if (tape.playing && tape.deactivate_display)
2140 TapeDeactivateDisplayOff(TRUE);
2142 SetMouseCursor(CURSOR_DEFAULT);
2144 #if defined(NETWORK_AVALIABLE)
2145 /* pause network game while waiting for request to answer */
2146 if (options.network &&
2147 game_status == GAME_MODE_PLAYING &&
2148 req_state & REQUEST_WAIT_FOR_INPUT)
2149 SendToServer_PausePlaying();
2152 old_door_state = GetDoorState();
2154 /* simulate releasing mouse button over last gadget, if still pressed */
2156 HandleGadgets(-1, -1, 0);
2160 if (old_door_state & DOOR_OPEN_1)
2162 CloseDoor(DOOR_CLOSE_1);
2164 /* save old door content */
2165 BlitBitmap(bitmap_db_door, bitmap_db_door,
2166 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
2167 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
2170 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
2172 /* clear door drawing field */
2173 DrawBackground(DX, DY, DXSIZE, DYSIZE);
2175 /* force DOOR font on preview level */
2176 game_status = GAME_MODE_PSEUDO_DOOR;
2178 /* write text for request */
2179 for (ty = 0; ty < MAX_REQUEST_LINES; ty++)
2181 char text_line[max_request_line_len + 1];
2187 for (tl = 0, tx = 0; tx < max_request_line_len; tl++, tx++)
2190 if (!tc || tc == ' ')
2201 strncpy(text_line, text, tl);
2204 DrawText(DX + (DXSIZE - tl * getFontWidth(font_nr)) / 2,
2205 DY + 8 + ty * (getFontHeight(font_nr) + 2),
2206 text_line, font_nr);
2208 text += tl + (tc == ' ' ? 1 : 0);
2211 game_status = last_game_status; /* restore current game status */
2213 if (req_state & REQ_ASK)
2215 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
2216 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
2218 else if (req_state & REQ_CONFIRM)
2220 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
2222 else if (req_state & REQ_PLAYER)
2224 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
2225 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
2226 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
2227 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
2230 /* copy request gadgets to door backbuffer */
2231 BlitBitmap(drawto, bitmap_db_door,
2232 DX, DY, DXSIZE, DYSIZE,
2233 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2235 OpenDoor(DOOR_OPEN_1);
2237 if (!(req_state & REQUEST_WAIT_FOR_INPUT))
2239 SetDrawBackgroundMask(REDRAW_FIELD);
2244 if (game_status != GAME_MODE_MAIN)
2247 button_status = MB_RELEASED;
2249 request_gadget_id = -1;
2251 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
2263 case EVENT_BUTTONPRESS:
2264 case EVENT_BUTTONRELEASE:
2265 case EVENT_MOTIONNOTIFY:
2267 if (event.type == EVENT_MOTIONNOTIFY)
2269 if (!PointerInWindow(window))
2270 continue; /* window and pointer are on different screens */
2275 motion_status = TRUE;
2276 mx = ((MotionEvent *) &event)->x;
2277 my = ((MotionEvent *) &event)->y;
2281 motion_status = FALSE;
2282 mx = ((ButtonEvent *) &event)->x;
2283 my = ((ButtonEvent *) &event)->y;
2284 if (event.type == EVENT_BUTTONPRESS)
2285 button_status = ((ButtonEvent *) &event)->button;
2287 button_status = MB_RELEASED;
2290 /* this sets 'request_gadget_id' */
2291 HandleGadgets(mx, my, button_status);
2293 switch(request_gadget_id)
2295 case TOOL_CTRL_ID_YES:
2298 case TOOL_CTRL_ID_NO:
2301 case TOOL_CTRL_ID_CONFIRM:
2302 result = TRUE | FALSE;
2305 case TOOL_CTRL_ID_PLAYER_1:
2308 case TOOL_CTRL_ID_PLAYER_2:
2311 case TOOL_CTRL_ID_PLAYER_3:
2314 case TOOL_CTRL_ID_PLAYER_4:
2325 case EVENT_KEYPRESS:
2326 switch(GetEventKey((KeyEvent *)&event, TRUE))
2339 if (req_state & REQ_PLAYER)
2343 case EVENT_KEYRELEASE:
2344 ClearPlayerAction();
2348 HandleOtherEvents(&event);
2352 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2354 int joy = AnyJoystick();
2356 if (joy & JOY_BUTTON_1)
2358 else if (joy & JOY_BUTTON_2)
2364 /* don't eat all CPU time */
2368 if (game_status != GAME_MODE_MAIN)
2373 if (!(req_state & REQ_STAY_OPEN))
2375 CloseDoor(DOOR_CLOSE_1);
2377 if (((old_door_state & DOOR_OPEN_1) && !(req_state & REQ_STAY_CLOSED)) ||
2378 (req_state & REQ_REOPEN))
2379 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
2384 SetDrawBackgroundMask(REDRAW_FIELD);
2386 #if defined(NETWORK_AVALIABLE)
2387 /* continue network game after request */
2388 if (options.network &&
2389 game_status == GAME_MODE_PLAYING &&
2390 req_state & REQUEST_WAIT_FOR_INPUT)
2391 SendToServer_ContinuePlaying();
2394 /* restore deactivated drawing when quick-loading level tape recording */
2395 if (tape.playing && tape.deactivate_display)
2396 TapeDeactivateDisplayOn();
2401 unsigned int OpenDoor(unsigned int door_state)
2403 if (door_state & DOOR_COPY_BACK)
2405 if (door_state & DOOR_OPEN_1)
2406 BlitBitmap(bitmap_db_door, bitmap_db_door,
2407 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
2408 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2410 if (door_state & DOOR_OPEN_2)
2411 BlitBitmap(bitmap_db_door, bitmap_db_door,
2412 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY2, VXSIZE, VYSIZE,
2413 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2415 door_state &= ~DOOR_COPY_BACK;
2418 return MoveDoor(door_state);
2421 unsigned int CloseDoor(unsigned int door_state)
2423 unsigned int old_door_state = GetDoorState();
2425 if (!(door_state & DOOR_NO_COPY_BACK))
2427 if (old_door_state & DOOR_OPEN_1)
2428 BlitBitmap(backbuffer, bitmap_db_door,
2429 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2431 if (old_door_state & DOOR_OPEN_2)
2432 BlitBitmap(backbuffer, bitmap_db_door,
2433 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2435 door_state &= ~DOOR_NO_COPY_BACK;
2438 return MoveDoor(door_state);
2441 unsigned int GetDoorState()
2443 return MoveDoor(DOOR_GET_STATE);
2446 unsigned int SetDoorState(unsigned int door_state)
2448 return MoveDoor(door_state | DOOR_SET_STATE);
2451 unsigned int MoveDoor(unsigned int door_state)
2453 static int door1 = DOOR_OPEN_1;
2454 static int door2 = DOOR_CLOSE_2;
2455 unsigned long door_delay = 0;
2456 unsigned long door_delay_value;
2459 if (door_1.width < 0 || door_1.width > DXSIZE)
2460 door_1.width = DXSIZE;
2461 if (door_1.height < 0 || door_1.height > DYSIZE)
2462 door_1.height = DYSIZE;
2463 if (door_2.width < 0 || door_2.width > VXSIZE)
2464 door_2.width = VXSIZE;
2465 if (door_2.height < 0 || door_2.height > VYSIZE)
2466 door_2.height = VYSIZE;
2468 if (door_state == DOOR_GET_STATE)
2469 return(door1 | door2);
2471 if (door_state & DOOR_SET_STATE)
2473 if (door_state & DOOR_ACTION_1)
2474 door1 = door_state & DOOR_ACTION_1;
2475 if (door_state & DOOR_ACTION_2)
2476 door2 = door_state & DOOR_ACTION_2;
2478 return(door1 | door2);
2481 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2482 door_state &= ~DOOR_OPEN_1;
2483 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2484 door_state &= ~DOOR_CLOSE_1;
2485 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2486 door_state &= ~DOOR_OPEN_2;
2487 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2488 door_state &= ~DOOR_CLOSE_2;
2490 door_delay_value = (door_state & DOOR_ACTION_1 ? door_1.step_delay :
2493 if (setup.quick_doors)
2495 stepsize = 20; /* must be choosen to always draw last frame */
2496 door_delay_value = 0;
2499 if (global.autoplay_leveldir)
2501 door_state |= DOOR_NO_DELAY;
2502 door_state &= ~DOOR_CLOSE_ALL;
2505 if (door_state & DOOR_ACTION)
2507 boolean handle_door_1 = (door_state & DOOR_ACTION_1);
2508 boolean handle_door_2 = (door_state & DOOR_ACTION_2);
2509 boolean door_1_done = (!handle_door_1);
2510 boolean door_2_done = (!handle_door_2);
2511 boolean door_1_vertical = (door_1.anim_mode & ANIM_VERTICAL);
2512 boolean door_2_vertical = (door_2.anim_mode & ANIM_VERTICAL);
2513 int door_size_1 = (door_1_vertical ? door_1.height : door_1.width);
2514 int door_size_2 = (door_2_vertical ? door_2.height : door_2.width);
2515 int max_door_size_1 = (door_1_vertical ? DYSIZE : DXSIZE);
2516 int max_door_size_2 = (door_2_vertical ? VYSIZE : VXSIZE);
2517 int door_size = (handle_door_1 ? door_size_1 : door_size_2);
2518 int max_door_size = (handle_door_1 ? max_door_size_1 : max_door_size_2);
2519 int door_skip = max_door_size - door_size;
2521 int end = door_size;
2523 int end = (door_state & DOOR_ACTION_1 &&
2524 door_1.anim_mode & ANIM_VERTICAL ? DYSIZE : DXSIZE);
2527 int start = ((door_state & DOOR_NO_DELAY) ? end : 0);
2529 int start = ((door_state & DOOR_NO_DELAY) ? end : offset_skip);
2533 if (!(door_state & DOOR_NO_DELAY) && !setup.quick_doors)
2535 /* opening door sound has priority over simultaneously closing door */
2536 if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
2537 PlaySoundStereo(SND_DOOR_OPENING, SOUND_MIDDLE);
2538 else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
2539 PlaySoundStereo(SND_DOOR_CLOSING, SOUND_MIDDLE);
2542 for (k = start; k <= end && !(door_1_done && door_2_done); k += stepsize)
2545 Bitmap *bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2546 GC gc = bitmap->stored_clip_gc;
2548 if (door_state & DOOR_ACTION_1)
2550 int a = MIN(x * door_1.step_offset, end);
2551 int p = (door_state & DOOR_OPEN_1 ? end - a : a);
2552 int i = p + door_skip;
2554 if (door_1.anim_mode & ANIM_STATIC_PANEL)
2556 BlitBitmap(bitmap_db_door, drawto,
2557 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1,
2558 DXSIZE, DYSIZE, DX, DY);
2562 BlitBitmap(bitmap_db_door, drawto,
2563 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + p / 2,
2564 DXSIZE, DYSIZE - p / 2, DX, DY);
2566 ClearRectangle(drawto, DX, DY + DYSIZE - p / 2, DXSIZE, p / 2);
2569 if (door_1.anim_mode & ANIM_HORIZONTAL && x <= DXSIZE)
2571 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
2572 int dst1_x = DX + DXSIZE - i, dst1_y = DY;
2573 int src2_x = DXSIZE - i, src2_y = DOOR_GFX_PAGEY1;
2574 int dst2_x = DX, dst2_y = DY;
2575 int width = i, height = DYSIZE;
2577 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2578 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2581 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2582 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2585 else if (door_1.anim_mode & ANIM_VERTICAL && x <= DYSIZE)
2587 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
2588 int dst1_x = DX, dst1_y = DY + DYSIZE - i;
2589 int src2_x = 0, src2_y = DOOR_GFX_PAGEY1 + DYSIZE - i;
2590 int dst2_x = DX, dst2_y = DY;
2591 int width = DXSIZE, height = i;
2593 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2594 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2597 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2598 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2601 else if (x <= DXSIZE) /* ANIM_DEFAULT */
2603 int j = (door_1.anim_mode == ANIM_DEFAULT ? (DXSIZE - i) / 3 : 0);
2605 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2606 BlitBitmapMasked(bitmap, drawto,
2607 DXSIZE, DOOR_GFX_PAGEY1, i, 77,
2608 DX + DXSIZE - i, DY + j);
2609 BlitBitmapMasked(bitmap, drawto,
2610 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
2611 DX + DXSIZE - i, DY + 140 + j);
2612 SetClipOrigin(bitmap, gc, DX - DXSIZE + i,
2613 DY - (DOOR_GFX_PAGEY1 + j));
2614 BlitBitmapMasked(bitmap, drawto,
2615 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
2617 BlitBitmapMasked(bitmap, drawto,
2618 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
2621 BlitBitmapMasked(bitmap, drawto,
2622 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2624 BlitBitmapMasked(bitmap, drawto,
2625 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2627 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2628 BlitBitmapMasked(bitmap, drawto,
2629 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2630 DX + DXSIZE - i, DY + 77 + j);
2631 BlitBitmapMasked(bitmap, drawto,
2632 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2633 DX + DXSIZE - i, DY + 203 + j);
2636 redraw_mask |= REDRAW_DOOR_1;
2637 door_1_done = (a == end);
2640 if (door_state & DOOR_ACTION_2)
2642 int a = MIN(x * door_2.step_offset, door_size_2);
2643 int p = (door_state & DOOR_OPEN_2 ? door_size_2 - a : a);
2644 int i = p + door_skip;
2646 if (door_2.anim_mode & ANIM_STATIC_PANEL)
2648 BlitBitmap(bitmap_db_door, drawto,
2649 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2,
2650 VXSIZE, VYSIZE, VX, VY);
2652 else if (x <= VYSIZE)
2654 BlitBitmap(bitmap_db_door, drawto,
2655 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + p / 2,
2656 VXSIZE, VYSIZE - p / 2, VX, VY);
2658 ClearRectangle(drawto, VX, VY + VYSIZE - p / 2, VXSIZE, p / 2);
2661 if (door_2.anim_mode & ANIM_HORIZONTAL && x <= VXSIZE)
2663 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
2664 int dst1_x = VX + VXSIZE - i, dst1_y = VY;
2665 int src2_x = VXSIZE - i, src2_y = DOOR_GFX_PAGEY2;
2666 int dst2_x = VX, dst2_y = VY;
2667 int width = i, height = VYSIZE;
2669 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2670 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2673 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2674 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2677 else if (door_2.anim_mode & ANIM_VERTICAL && x <= VYSIZE)
2679 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
2680 int dst1_x = VX, dst1_y = VY + VYSIZE - i;
2681 int src2_x = 0, src2_y = DOOR_GFX_PAGEY2 + VYSIZE - i;
2682 int dst2_x = VX, dst2_y = VY;
2683 int width = VXSIZE, height = i;
2685 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2686 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2689 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2690 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2693 else if (x <= VXSIZE) /* ANIM_DEFAULT */
2695 int j = (door_2.anim_mode == ANIM_DEFAULT ? (VXSIZE - i) / 3 : 0);
2697 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2698 BlitBitmapMasked(bitmap, drawto,
2699 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
2700 VX + VXSIZE - i, VY + j);
2701 SetClipOrigin(bitmap, gc,
2702 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2703 BlitBitmapMasked(bitmap, drawto,
2704 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
2707 BlitBitmapMasked(bitmap, drawto,
2708 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2709 i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
2710 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2711 BlitBitmapMasked(bitmap, drawto,
2712 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2714 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2717 redraw_mask |= REDRAW_DOOR_2;
2718 door_2_done = (a == VXSIZE);
2723 if (game_status == GAME_MODE_MAIN)
2726 if (!(door_state & DOOR_NO_DELAY))
2727 WaitUntilDelayReached(&door_delay, door_delay_value);
2731 if (door_state & DOOR_ACTION_1)
2732 door1 = door_state & DOOR_ACTION_1;
2733 if (door_state & DOOR_ACTION_2)
2734 door2 = door_state & DOOR_ACTION_2;
2736 return (door1 | door2);
2739 void DrawSpecialEditorDoor()
2741 /* draw bigger toolbox window */
2742 BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
2743 DOOR_GFX_PAGEX7, 0, EXSIZE + 8, 8,
2745 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2746 EX - 6, VY - 4, EXSIZE + 12, EYSIZE - VYSIZE + 4,
2749 redraw_mask |= REDRAW_ALL;
2752 void UndrawSpecialEditorDoor()
2754 /* draw normal tape recorder window */
2755 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2756 EX - 6, EY - 12, EXSIZE + 12, EYSIZE - VYSIZE + 12,
2759 redraw_mask |= REDRAW_ALL;
2763 /* ---------- new tool button stuff ---------------------------------------- */
2765 /* graphic position values for tool buttons */
2766 #define TOOL_BUTTON_YES_XPOS 2
2767 #define TOOL_BUTTON_YES_YPOS 250
2768 #define TOOL_BUTTON_YES_GFX_YPOS 0
2769 #define TOOL_BUTTON_YES_XSIZE 46
2770 #define TOOL_BUTTON_YES_YSIZE 28
2771 #define TOOL_BUTTON_NO_XPOS 52
2772 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2773 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2774 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2775 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2776 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2777 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2778 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2779 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2780 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2781 #define TOOL_BUTTON_PLAYER_XSIZE 30
2782 #define TOOL_BUTTON_PLAYER_YSIZE 30
2783 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2784 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2785 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2786 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2787 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2788 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2789 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2790 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2791 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2792 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2793 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2794 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2795 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2796 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2797 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2798 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2799 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2800 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2801 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2802 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2811 } toolbutton_info[NUM_TOOL_BUTTONS] =
2814 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2815 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2816 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2821 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2822 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2823 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2828 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2829 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2830 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2831 TOOL_CTRL_ID_CONFIRM,
2835 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2836 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2837 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2838 TOOL_CTRL_ID_PLAYER_1,
2842 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2843 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2844 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2845 TOOL_CTRL_ID_PLAYER_2,
2849 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2850 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2851 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2852 TOOL_CTRL_ID_PLAYER_3,
2856 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2857 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2858 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2859 TOOL_CTRL_ID_PLAYER_4,
2864 void CreateToolButtons()
2868 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2870 Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2871 Bitmap *deco_bitmap = None;
2872 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2873 struct GadgetInfo *gi;
2874 unsigned long event_mask;
2875 int gd_xoffset, gd_yoffset;
2876 int gd_x1, gd_x2, gd_y;
2879 event_mask = GD_EVENT_RELEASED;
2881 gd_xoffset = toolbutton_info[i].xpos;
2882 gd_yoffset = toolbutton_info[i].ypos;
2883 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2884 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2885 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2887 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2889 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
2891 getMiniGraphicSource(PLAYER_NR_GFX(IMG_PLAYER_1, player_nr),
2892 &deco_bitmap, &deco_x, &deco_y);
2893 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2894 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2897 gi = CreateGadget(GDI_CUSTOM_ID, id,
2898 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2899 GDI_X, DX + toolbutton_info[i].x,
2900 GDI_Y, DY + toolbutton_info[i].y,
2901 GDI_WIDTH, toolbutton_info[i].width,
2902 GDI_HEIGHT, toolbutton_info[i].height,
2903 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2904 GDI_STATE, GD_BUTTON_UNPRESSED,
2905 GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
2906 GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
2907 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
2908 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2909 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2910 GDI_DECORATION_SHIFTING, 1, 1,
2911 GDI_EVENT_MASK, event_mask,
2912 GDI_CALLBACK_ACTION, HandleToolButtons,
2916 Error(ERR_EXIT, "cannot create gadget");
2918 tool_gadget[id] = gi;
2922 void FreeToolButtons()
2926 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2927 FreeGadget(tool_gadget[i]);
2930 static void UnmapToolButtons()
2934 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2935 UnmapGadget(tool_gadget[i]);
2938 static void HandleToolButtons(struct GadgetInfo *gi)
2940 request_gadget_id = gi->custom_id;
2943 static struct Mapping_EM_to_RND_object
2946 boolean is_rnd_to_em_mapping; /* unique mapping EM <-> RND */
2947 boolean is_backside; /* backside of moving element */
2953 em_object_mapping_list[] =
2956 Xblank, TRUE, FALSE,
2960 Yacid_splash_eB, FALSE, FALSE,
2961 EL_ACID_SPLASH_RIGHT, -1, -1
2964 Yacid_splash_wB, FALSE, FALSE,
2965 EL_ACID_SPLASH_LEFT, -1, -1
2968 #ifdef EM_ENGINE_BAD_ROLL
2970 Xstone_force_e, FALSE, FALSE,
2971 EL_ROCK, -1, MV_BIT_RIGHT
2974 Xstone_force_w, FALSE, FALSE,
2975 EL_ROCK, -1, MV_BIT_LEFT
2978 Xnut_force_e, FALSE, FALSE,
2979 EL_NUT, -1, MV_BIT_RIGHT
2982 Xnut_force_w, FALSE, FALSE,
2983 EL_NUT, -1, MV_BIT_LEFT
2986 Xspring_force_e, FALSE, FALSE,
2987 EL_SPRING, -1, MV_BIT_RIGHT
2990 Xspring_force_w, FALSE, FALSE,
2991 EL_SPRING, -1, MV_BIT_LEFT
2994 Xemerald_force_e, FALSE, FALSE,
2995 EL_EMERALD, -1, MV_BIT_RIGHT
2998 Xemerald_force_w, FALSE, FALSE,
2999 EL_EMERALD, -1, MV_BIT_LEFT
3002 Xdiamond_force_e, FALSE, FALSE,
3003 EL_DIAMOND, -1, MV_BIT_RIGHT
3006 Xdiamond_force_w, FALSE, FALSE,
3007 EL_DIAMOND, -1, MV_BIT_LEFT
3010 Xbomb_force_e, FALSE, FALSE,
3011 EL_BOMB, -1, MV_BIT_RIGHT
3014 Xbomb_force_w, FALSE, FALSE,
3015 EL_BOMB, -1, MV_BIT_LEFT
3017 #endif /* EM_ENGINE_BAD_ROLL */
3020 Xstone, TRUE, FALSE,
3024 Xstone_pause, FALSE, FALSE,
3028 Xstone_fall, FALSE, FALSE,
3032 Ystone_s, FALSE, FALSE,
3033 EL_ROCK, ACTION_FALLING, -1
3036 Ystone_sB, FALSE, TRUE,
3037 EL_ROCK, ACTION_FALLING, -1
3040 Ystone_e, FALSE, FALSE,
3041 EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT
3044 Ystone_eB, FALSE, TRUE,
3045 EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT
3048 Ystone_w, FALSE, FALSE,
3049 EL_ROCK, ACTION_MOVING, MV_BIT_LEFT
3052 Ystone_wB, FALSE, TRUE,
3053 EL_ROCK, ACTION_MOVING, MV_BIT_LEFT
3060 Xnut_pause, FALSE, FALSE,
3064 Xnut_fall, FALSE, FALSE,
3068 Ynut_s, FALSE, FALSE,
3069 EL_NUT, ACTION_FALLING, -1
3072 Ynut_sB, FALSE, TRUE,
3073 EL_NUT, ACTION_FALLING, -1
3076 Ynut_e, FALSE, FALSE,
3077 EL_NUT, ACTION_MOVING, MV_BIT_RIGHT
3080 Ynut_eB, FALSE, TRUE,
3081 EL_NUT, ACTION_MOVING, MV_BIT_RIGHT
3084 Ynut_w, FALSE, FALSE,
3085 EL_NUT, ACTION_MOVING, MV_BIT_LEFT
3088 Ynut_wB, FALSE, TRUE,
3089 EL_NUT, ACTION_MOVING, MV_BIT_LEFT
3092 Xbug_n, TRUE, FALSE,
3096 Xbug_e, TRUE, FALSE,
3097 EL_BUG_RIGHT, -1, -1
3100 Xbug_s, TRUE, FALSE,
3104 Xbug_w, TRUE, FALSE,
3108 Xbug_gon, FALSE, FALSE,
3112 Xbug_goe, FALSE, FALSE,
3113 EL_BUG_RIGHT, -1, -1
3116 Xbug_gos, FALSE, FALSE,
3120 Xbug_gow, FALSE, FALSE,
3124 Ybug_n, FALSE, FALSE,
3125 EL_BUG, ACTION_MOVING, MV_BIT_UP
3128 Ybug_nB, FALSE, TRUE,
3129 EL_BUG, ACTION_MOVING, MV_BIT_UP
3132 Ybug_e, FALSE, FALSE,
3133 EL_BUG, ACTION_MOVING, MV_BIT_RIGHT
3136 Ybug_eB, FALSE, TRUE,
3137 EL_BUG, ACTION_MOVING, MV_BIT_RIGHT
3140 Ybug_s, FALSE, FALSE,
3141 EL_BUG, ACTION_MOVING, MV_BIT_DOWN
3144 Ybug_sB, FALSE, TRUE,
3145 EL_BUG, ACTION_MOVING, MV_BIT_DOWN
3148 Ybug_w, FALSE, FALSE,
3149 EL_BUG, ACTION_MOVING, MV_BIT_LEFT
3152 Ybug_wB, FALSE, TRUE,
3153 EL_BUG, ACTION_MOVING, MV_BIT_LEFT
3156 Ybug_w_n, FALSE, FALSE,
3157 EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_UP
3160 Ybug_n_e, FALSE, FALSE,
3161 EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3164 Ybug_e_s, FALSE, FALSE,
3165 EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
3168 Ybug_s_w, FALSE, FALSE,
3169 EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3172 Ybug_e_n, FALSE, FALSE,
3173 EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
3176 Ybug_s_e, FALSE, FALSE,
3177 EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3180 Ybug_w_s, FALSE, FALSE,
3181 EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
3184 Ybug_n_w, FALSE, FALSE,
3185 EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3188 Ybug_stone, FALSE, FALSE,
3189 EL_BUG, ACTION_SMASHED_BY_ROCK, -1
3192 Ybug_spring, FALSE, FALSE,
3193 EL_BUG, ACTION_SMASHED_BY_SPRING, -1
3196 Xtank_n, TRUE, FALSE,
3197 EL_SPACESHIP_UP, -1, -1
3200 Xtank_e, TRUE, FALSE,
3201 EL_SPACESHIP_RIGHT, -1, -1
3204 Xtank_s, TRUE, FALSE,
3205 EL_SPACESHIP_DOWN, -1, -1
3208 Xtank_w, TRUE, FALSE,
3209 EL_SPACESHIP_LEFT, -1, -1
3212 Xtank_gon, FALSE, FALSE,
3213 EL_SPACESHIP_UP, -1, -1
3216 Xtank_goe, FALSE, FALSE,
3217 EL_SPACESHIP_RIGHT, -1, -1
3220 Xtank_gos, FALSE, FALSE,
3221 EL_SPACESHIP_DOWN, -1, -1
3224 Xtank_gow, FALSE, FALSE,
3225 EL_SPACESHIP_LEFT, -1, -1
3228 Ytank_n, FALSE, FALSE,
3229 EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP
3232 Ytank_nB, FALSE, TRUE,
3233 EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP
3236 Ytank_e, FALSE, FALSE,
3237 EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT
3240 Ytank_eB, FALSE, TRUE,
3241 EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT
3244 Ytank_s, FALSE, FALSE,
3245 EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN
3248 Ytank_sB, FALSE, TRUE,
3249 EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN
3252 Ytank_w, FALSE, FALSE,
3253 EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT
3256 Ytank_wB, FALSE, TRUE,
3257 EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT
3260 Ytank_w_n, FALSE, FALSE,
3261 EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_UP
3264 Ytank_n_e, FALSE, FALSE,
3265 EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3268 Ytank_e_s, FALSE, FALSE,
3269 EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
3272 Ytank_s_w, FALSE, FALSE,
3273 EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3276 Ytank_e_n, FALSE, FALSE,
3277 EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
3280 Ytank_s_e, FALSE, FALSE,
3281 EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3284 Ytank_w_s, FALSE, FALSE,
3285 EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
3288 Ytank_n_w, FALSE, FALSE,
3289 EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3292 Ytank_stone, FALSE, FALSE,
3293 EL_SPACESHIP, ACTION_SMASHED_BY_ROCK, -1
3296 Ytank_spring, FALSE, FALSE,
3297 EL_SPACESHIP, ACTION_SMASHED_BY_SPRING, -1
3300 Xandroid, TRUE, FALSE,
3301 EL_EMC_ANDROID, ACTION_ACTIVE, -1
3304 Xandroid_1_n, FALSE, FALSE,
3305 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_UP
3308 Xandroid_2_n, FALSE, FALSE,
3309 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_UP
3312 Xandroid_1_e, FALSE, FALSE,
3313 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_RIGHT
3316 Xandroid_2_e, FALSE, FALSE,
3317 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_RIGHT
3320 Xandroid_1_w, FALSE, FALSE,
3321 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_LEFT
3324 Xandroid_2_w, FALSE, FALSE,
3325 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_LEFT
3328 Xandroid_1_s, FALSE, FALSE,
3329 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_DOWN
3332 Xandroid_2_s, FALSE, FALSE,
3333 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_DOWN
3336 Yandroid_n, FALSE, FALSE,
3337 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_UP
3340 Yandroid_nB, FALSE, TRUE,
3341 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_UP
3344 Yandroid_ne, FALSE, FALSE,
3345 EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_UPRIGHT
3348 Yandroid_neB, FALSE, TRUE,
3349 EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_UPRIGHT
3352 Yandroid_e, FALSE, FALSE,
3353 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_RIGHT
3356 Yandroid_eB, FALSE, TRUE,
3357 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_RIGHT
3360 Yandroid_se, FALSE, FALSE,
3361 EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_DOWNRIGHT
3364 Yandroid_seB, FALSE, TRUE,
3365 EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_DOWNRIGHT
3368 Yandroid_s, FALSE, FALSE,
3369 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_DOWN
3372 Yandroid_sB, FALSE, TRUE,
3373 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_DOWN
3376 Yandroid_sw, FALSE, FALSE,
3377 EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_DOWNLEFT
3380 Yandroid_swB, FALSE, TRUE,
3381 EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_DOWNLEFT
3384 Yandroid_w, FALSE, FALSE,
3385 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_LEFT
3388 Yandroid_wB, FALSE, TRUE,
3389 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_LEFT
3392 Yandroid_nw, FALSE, FALSE,
3393 EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_UPLEFT
3396 Yandroid_nwB, FALSE, TRUE,
3397 EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_UPLEFT
3400 Xspring, TRUE, FALSE,
3404 Xspring_pause, FALSE, FALSE,
3408 Xspring_e, FALSE, FALSE,
3412 Xspring_w, FALSE, FALSE,
3416 Xspring_fall, FALSE, FALSE,
3420 Yspring_s, FALSE, FALSE,
3421 EL_SPRING, ACTION_FALLING, -1
3424 Yspring_sB, FALSE, TRUE,
3425 EL_SPRING, ACTION_FALLING, -1
3428 Yspring_e, FALSE, FALSE,
3429 EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT
3432 Yspring_eB, FALSE, TRUE,
3433 EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT
3436 Yspring_w, FALSE, FALSE,
3437 EL_SPRING, ACTION_MOVING, MV_BIT_LEFT
3440 Yspring_wB, FALSE, TRUE,
3441 EL_SPRING, ACTION_MOVING, MV_BIT_LEFT
3444 Yspring_kill_e, FALSE, FALSE,
3445 EL_SPRING, ACTION_EATING, MV_BIT_RIGHT
3448 Yspring_kill_eB, FALSE, TRUE,
3449 EL_SPRING, ACTION_EATING, MV_BIT_RIGHT
3452 Yspring_kill_w, FALSE, FALSE,
3453 EL_SPRING, ACTION_EATING, MV_BIT_LEFT
3456 Yspring_kill_wB, FALSE, TRUE,
3457 EL_SPRING, ACTION_EATING, MV_BIT_LEFT
3460 Xeater_n, TRUE, FALSE,
3464 Xeater_e, FALSE, FALSE,
3468 Xeater_w, FALSE, FALSE,
3472 Xeater_s, FALSE, FALSE,
3476 Yeater_n, FALSE, FALSE,
3477 EL_YAMYAM, ACTION_MOVING, MV_BIT_UP
3480 Yeater_nB, FALSE, TRUE,
3481 EL_YAMYAM, ACTION_MOVING, MV_BIT_UP
3484 Yeater_e, FALSE, FALSE,
3485 EL_YAMYAM, ACTION_MOVING, MV_BIT_RIGHT
3488 Yeater_eB, FALSE, TRUE,
3489 EL_YAMYAM, ACTION_MOVING, MV_BIT_RIGHT
3492 Yeater_s, FALSE, FALSE,
3493 EL_YAMYAM, ACTION_MOVING, MV_BIT_DOWN
3496 Yeater_sB, FALSE, TRUE,
3497 EL_YAMYAM, ACTION_MOVING, MV_BIT_DOWN
3500 Yeater_w, FALSE, FALSE,
3501 EL_YAMYAM, ACTION_MOVING, MV_BIT_LEFT
3504 Yeater_wB, FALSE, TRUE,
3505 EL_YAMYAM, ACTION_MOVING, MV_BIT_LEFT
3508 Yeater_stone, FALSE, FALSE,
3509 EL_YAMYAM, ACTION_SMASHED_BY_ROCK, -1
3512 Yeater_spring, FALSE, FALSE,
3513 EL_YAMYAM, ACTION_SMASHED_BY_SPRING, -1
3516 Xalien, TRUE, FALSE,
3520 Xalien_pause, FALSE, FALSE,
3524 Yalien_n, FALSE, FALSE,
3525 EL_ROBOT, ACTION_MOVING, MV_BIT_UP
3528 Yalien_nB, FALSE, TRUE,
3529 EL_ROBOT, ACTION_MOVING, MV_BIT_UP
3532 Yalien_e, FALSE, FALSE,
3533 EL_ROBOT, ACTION_MOVING, MV_BIT_RIGHT
3536 Yalien_eB, FALSE, TRUE,
3537 EL_ROBOT, ACTION_MOVING, MV_BIT_RIGHT
3540 Yalien_s, FALSE, FALSE,
3541 EL_ROBOT, ACTION_MOVING, MV_BIT_DOWN
3544 Yalien_sB, FALSE, TRUE,
3545 EL_ROBOT, ACTION_MOVING, MV_BIT_DOWN
3548 Yalien_w, FALSE, FALSE,
3549 EL_ROBOT, ACTION_MOVING, MV_BIT_LEFT
3552 Yalien_wB, FALSE, TRUE,
3553 EL_ROBOT, ACTION_MOVING, MV_BIT_LEFT
3556 Yalien_stone, FALSE, FALSE,
3557 EL_ROBOT, ACTION_SMASHED_BY_ROCK, -1
3560 Yalien_spring, FALSE, FALSE,
3561 EL_ROBOT, ACTION_SMASHED_BY_SPRING, -1
3564 Xemerald, TRUE, FALSE,
3568 Xemerald_pause, FALSE, FALSE,
3572 Xemerald_fall, FALSE, FALSE,
3576 Xemerald_shine, FALSE, FALSE,
3577 EL_EMERALD, ACTION_TWINKLING, -1
3580 Yemerald_s, FALSE, FALSE,
3581 EL_EMERALD, ACTION_FALLING, -1
3584 Yemerald_sB, FALSE, TRUE,
3585 EL_EMERALD, ACTION_FALLING, -1
3588 Yemerald_e, FALSE, FALSE,
3589 EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT
3592 Yemerald_eB, FALSE, TRUE,
3593 EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT
3596 Yemerald_w, FALSE, FALSE,
3597 EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT
3600 Yemerald_wB, FALSE, TRUE,
3601 EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT
3604 Yemerald_eat, FALSE, FALSE,
3605 EL_EMERALD, ACTION_COLLECTING, -1
3608 Yemerald_stone, FALSE, FALSE,
3609 EL_NUT, ACTION_BREAKING, -1
3612 Xdiamond, TRUE, FALSE,
3616 Xdiamond_pause, FALSE, FALSE,
3620 Xdiamond_fall, FALSE, FALSE,
3624 Xdiamond_shine, FALSE, FALSE,
3625 EL_DIAMOND, ACTION_TWINKLING, -1
3628 Ydiamond_s, FALSE, FALSE,
3629 EL_DIAMOND, ACTION_FALLING, -1
3632 Ydiamond_sB, FALSE, TRUE,
3633 EL_DIAMOND, ACTION_FALLING, -1
3636 Ydiamond_e, FALSE, FALSE,
3637 EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT
3640 Ydiamond_eB, FALSE, TRUE,
3641 EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT
3644 Ydiamond_w, FALSE, FALSE,
3645 EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT
3648 Ydiamond_wB, FALSE, TRUE,
3649 EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT
3652 Ydiamond_eat, FALSE, FALSE,
3653 EL_DIAMOND, ACTION_COLLECTING, -1
3656 Ydiamond_stone, FALSE, FALSE,
3657 EL_DIAMOND, ACTION_SMASHED_BY_ROCK, -1
3660 Xdrip_fall, TRUE, FALSE,
3661 EL_AMOEBA_DROP, -1, -1
3664 Xdrip_stretch, FALSE, FALSE,
3665 EL_AMOEBA_DROP, ACTION_FALLING, -1
3668 Xdrip_stretchB, FALSE, TRUE,
3669 EL_AMOEBA_DROP, ACTION_FALLING, -1
3672 Xdrip_eat, FALSE, FALSE,
3673 EL_AMOEBA_DROP, ACTION_GROWING, -1
3676 Ydrip_s1, FALSE, FALSE,
3677 EL_AMOEBA_DROP, ACTION_FALLING, -1
3680 Ydrip_s1B, FALSE, TRUE,
3681 EL_AMOEBA_DROP, ACTION_FALLING, -1
3684 Ydrip_s2, FALSE, FALSE,
3685 EL_AMOEBA_DROP, ACTION_FALLING, -1
3688 Ydrip_s2B, FALSE, TRUE,
3689 EL_AMOEBA_DROP, ACTION_FALLING, -1
3696 Xbomb_pause, FALSE, FALSE,
3700 Xbomb_fall, FALSE, FALSE,
3704 Ybomb_s, FALSE, FALSE,
3705 EL_BOMB, ACTION_FALLING, -1
3708 Ybomb_sB, FALSE, TRUE,
3709 EL_BOMB, ACTION_FALLING, -1
3712 Ybomb_e, FALSE, FALSE,
3713 EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT
3716 Ybomb_eB, FALSE, TRUE,
3717 EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT
3720 Ybomb_w, FALSE, FALSE,
3721 EL_BOMB, ACTION_MOVING, MV_BIT_LEFT
3724 Ybomb_wB, FALSE, TRUE,
3725 EL_BOMB, ACTION_MOVING, MV_BIT_LEFT
3728 Ybomb_eat, FALSE, FALSE,
3729 EL_BOMB, ACTION_ACTIVATING, -1
3732 Xballoon, TRUE, FALSE,
3736 Yballoon_n, FALSE, FALSE,
3737 EL_BALLOON, ACTION_MOVING, MV_BIT_UP
3740 Yballoon_nB, FALSE, TRUE,
3741 EL_BALLOON, ACTION_MOVING, MV_BIT_UP
3744 Yballoon_e, FALSE, FALSE,
3745 EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT
3748 Yballoon_eB, FALSE, TRUE,
3749 EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT
3752 Yballoon_s, FALSE, FALSE,
3753 EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN
3756 Yballoon_sB, FALSE, TRUE,
3757 EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN
3760 Yballoon_w, FALSE, FALSE,
3761 EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT
3764 Yballoon_wB, FALSE, TRUE,
3765 EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT
3768 Xgrass, TRUE, FALSE,
3769 EL_EMC_GRASS, -1, -1
3772 Ygrass_nB, FALSE, FALSE,
3773 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_UP
3776 Ygrass_eB, FALSE, FALSE,
3777 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_RIGHT
3780 Ygrass_sB, FALSE, FALSE,
3781 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_DOWN
3784 Ygrass_wB, FALSE, FALSE,
3785 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_LEFT
3792 Ydirt_nB, FALSE, FALSE,
3793 EL_SAND, ACTION_DIGGING, MV_BIT_UP
3796 Ydirt_eB, FALSE, FALSE,
3797 EL_SAND, ACTION_DIGGING, MV_BIT_RIGHT
3800 Ydirt_sB, FALSE, FALSE,
3801 EL_SAND, ACTION_DIGGING, MV_BIT_DOWN
3804 Ydirt_wB, FALSE, FALSE,
3805 EL_SAND, ACTION_DIGGING, MV_BIT_LEFT
3808 Xacid_ne, TRUE, FALSE,
3809 EL_ACID_POOL_TOPRIGHT, -1, -1
3812 Xacid_se, TRUE, FALSE,
3813 EL_ACID_POOL_BOTTOMRIGHT, -1, -1
3816 Xacid_s, TRUE, FALSE,
3817 EL_ACID_POOL_BOTTOM, -1, -1
3820 Xacid_sw, TRUE, FALSE,
3821 EL_ACID_POOL_BOTTOMLEFT, -1, -1
3824 Xacid_nw, TRUE, FALSE,
3825 EL_ACID_POOL_TOPLEFT, -1, -1
3828 Xacid_1, TRUE, FALSE,
3832 Xacid_2, FALSE, FALSE,
3836 Xacid_3, FALSE, FALSE,
3840 Xacid_4, FALSE, FALSE,
3844 Xacid_5, FALSE, FALSE,
3848 Xacid_6, FALSE, FALSE,
3852 Xacid_7, FALSE, FALSE,
3856 Xacid_8, FALSE, FALSE,
3860 Xball_1, TRUE, FALSE,
3861 EL_EMC_MAGIC_BALL, -1, -1
3864 Xball_1B, FALSE, FALSE,
3865 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
3868 Xball_2, FALSE, FALSE,
3869 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
3872 Xball_2B, FALSE, FALSE,
3873 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
3876 Yball_eat, FALSE, FALSE,
3877 EL_EMC_MAGIC_BALL, ACTION_DROPPING, -1
3880 Ykey_1_eat, FALSE, FALSE,
3881 EL_EM_KEY_1, ACTION_COLLECTING, -1
3884 Ykey_2_eat, FALSE, FALSE,
3885 EL_EM_KEY_2, ACTION_COLLECTING, -1
3888 Ykey_3_eat, FALSE, FALSE,
3889 EL_EM_KEY_3, ACTION_COLLECTING, -1
3892 Ykey_4_eat, FALSE, FALSE,
3893 EL_EM_KEY_4, ACTION_COLLECTING, -1
3896 Ykey_5_eat, FALSE, FALSE,
3897 EL_EMC_KEY_5, ACTION_COLLECTING, -1
3900 Ykey_6_eat, FALSE, FALSE,
3901 EL_EMC_KEY_6, ACTION_COLLECTING, -1
3904 Ykey_7_eat, FALSE, FALSE,
3905 EL_EMC_KEY_7, ACTION_COLLECTING, -1
3908 Ykey_8_eat, FALSE, FALSE,
3909 EL_EMC_KEY_8, ACTION_COLLECTING, -1
3912 Ylenses_eat, FALSE, FALSE,
3913 EL_EMC_LENSES, ACTION_COLLECTING, -1
3916 Ymagnify_eat, FALSE, FALSE,
3917 EL_EMC_MAGNIFIER, ACTION_COLLECTING, -1
3920 Ygrass_eat, FALSE, FALSE,
3921 EL_EMC_GRASS, ACTION_SNAPPING, -1
3924 Ydirt_eat, FALSE, FALSE,
3925 EL_SAND, ACTION_SNAPPING, -1
3928 Xgrow_ns, TRUE, FALSE,
3929 EL_EXPANDABLE_WALL_VERTICAL, -1, -1
3932 Ygrow_ns_eat, FALSE, FALSE,
3933 EL_EXPANDABLE_WALL_VERTICAL, ACTION_GROWING, -1
3936 Xgrow_ew, TRUE, FALSE,
3937 EL_EXPANDABLE_WALL_HORIZONTAL, -1, -1
3940 Ygrow_ew_eat, FALSE, FALSE,
3941 EL_EXPANDABLE_WALL_HORIZONTAL, ACTION_GROWING, -1
3944 Xwonderwall, TRUE, FALSE,
3945 EL_MAGIC_WALL, -1, -1
3948 XwonderwallB, FALSE, FALSE,
3949 EL_MAGIC_WALL, ACTION_ACTIVE, -1
3952 Xamoeba_1, TRUE, FALSE,
3953 EL_AMOEBA_DRY, ACTION_OTHER, -1
3956 Xamoeba_2, FALSE, FALSE,
3957 EL_AMOEBA_DRY, ACTION_OTHER, -1
3960 Xamoeba_3, FALSE, FALSE,
3961 EL_AMOEBA_DRY, ACTION_OTHER, -1
3964 Xamoeba_4, FALSE, FALSE,
3965 EL_AMOEBA_DRY, ACTION_OTHER, -1
3968 Xamoeba_5, TRUE, FALSE,
3969 EL_AMOEBA_WET, ACTION_OTHER, -1
3972 Xamoeba_6, FALSE, FALSE,
3973 EL_AMOEBA_WET, ACTION_OTHER, -1
3976 Xamoeba_7, FALSE, FALSE,
3977 EL_AMOEBA_WET, ACTION_OTHER, -1
3980 Xamoeba_8, FALSE, FALSE,
3981 EL_AMOEBA_WET, ACTION_OTHER, -1
3984 Xdoor_1, TRUE, FALSE,
3985 EL_EM_GATE_1, -1, -1
3988 Xdoor_2, TRUE, FALSE,
3989 EL_EM_GATE_2, -1, -1
3992 Xdoor_3, TRUE, FALSE,
3993 EL_EM_GATE_3, -1, -1
3996 Xdoor_4, TRUE, FALSE,
3997 EL_EM_GATE_4, -1, -1
4000 Xdoor_5, TRUE, FALSE,
4001 EL_EMC_GATE_5, -1, -1
4004 Xdoor_6, TRUE, FALSE,
4005 EL_EMC_GATE_6, -1, -1
4008 Xdoor_7, TRUE, FALSE,
4009 EL_EMC_GATE_7, -1, -1
4012 Xdoor_8, TRUE, FALSE,
4013 EL_EMC_GATE_8, -1, -1
4016 Xkey_1, TRUE, FALSE,
4020 Xkey_2, TRUE, FALSE,
4024 Xkey_3, TRUE, FALSE,
4028 Xkey_4, TRUE, FALSE,
4032 Xkey_5, TRUE, FALSE,
4033 EL_EMC_KEY_5, -1, -1
4036 Xkey_6, TRUE, FALSE,
4037 EL_EMC_KEY_6, -1, -1
4040 Xkey_7, TRUE, FALSE,
4041 EL_EMC_KEY_7, -1, -1
4044 Xkey_8, TRUE, FALSE,
4045 EL_EMC_KEY_8, -1, -1
4048 Xwind_n, TRUE, FALSE,
4049 EL_BALLOON_SWITCH_UP, -1, -1
4052 Xwind_e, TRUE, FALSE,
4053 EL_BALLOON_SWITCH_RIGHT, -1, -1
4056 Xwind_s, TRUE, FALSE,
4057 EL_BALLOON_SWITCH_DOWN, -1, -1
4060 Xwind_w, TRUE, FALSE,
4061 EL_BALLOON_SWITCH_LEFT, -1, -1
4064 Xwind_nesw, TRUE, FALSE,
4065 EL_BALLOON_SWITCH_ANY, -1, -1
4068 Xwind_stop, TRUE, FALSE,
4069 EL_BALLOON_SWITCH_NONE, -1, -1
4073 EL_EXIT_CLOSED, -1, -1
4076 Xexit_1, TRUE, FALSE,
4077 EL_EXIT_OPEN, -1, -1
4080 Xexit_2, FALSE, FALSE,
4081 EL_EXIT_OPEN, -1, -1
4084 Xexit_3, FALSE, FALSE,
4085 EL_EXIT_OPEN, -1, -1
4088 Xdynamite, TRUE, FALSE,
4089 EL_EM_DYNAMITE, -1, -1
4092 Ydynamite_eat, FALSE, FALSE,
4093 EL_EM_DYNAMITE, ACTION_COLLECTING, -1
4096 Xdynamite_1, TRUE, FALSE,
4097 EL_EM_DYNAMITE_ACTIVE, -1, -1
4100 Xdynamite_2, FALSE, FALSE,
4101 EL_EM_DYNAMITE_ACTIVE, -1, -1
4104 Xdynamite_3, FALSE, FALSE,
4105 EL_EM_DYNAMITE_ACTIVE, -1, -1
4108 Xdynamite_4, FALSE, FALSE,
4109 EL_EM_DYNAMITE_ACTIVE, -1, -1
4112 Xbumper, TRUE, FALSE,
4113 EL_EMC_SPRING_BUMPER, -1, -1
4116 XbumperB, FALSE, FALSE,
4117 EL_EMC_SPRING_BUMPER, ACTION_ACTIVE, -1
4120 Xwheel, TRUE, FALSE,
4121 EL_ROBOT_WHEEL, -1, -1
4124 XwheelB, FALSE, FALSE,
4125 EL_ROBOT_WHEEL, ACTION_ACTIVE, -1
4128 Xswitch, TRUE, FALSE,
4129 EL_EMC_MAGIC_BALL_SWITCH, -1, -1
4132 XswitchB, FALSE, FALSE,
4133 EL_EMC_MAGIC_BALL_SWITCH, ACTION_ACTIVE, -1
4137 EL_QUICKSAND_EMPTY, -1, -1
4140 Xsand_stone, TRUE, FALSE,
4141 EL_QUICKSAND_FULL, -1, -1
4144 Xsand_stonein_1, FALSE, FALSE,
4145 EL_ROCK, ACTION_FILLING, -1
4148 Xsand_stonein_2, FALSE, FALSE,
4149 EL_ROCK, ACTION_FILLING, -1
4152 Xsand_stonein_3, FALSE, FALSE,
4153 EL_ROCK, ACTION_FILLING, -1
4156 Xsand_stonein_4, FALSE, FALSE,
4157 EL_ROCK, ACTION_FILLING, -1
4160 Xsand_stonesand_1, FALSE, FALSE,
4161 EL_QUICKSAND_FULL, -1, -1
4164 Xsand_stonesand_2, FALSE, FALSE,
4165 EL_QUICKSAND_FULL, -1, -1
4168 Xsand_stonesand_3, FALSE, FALSE,
4169 EL_QUICKSAND_FULL, -1, -1
4172 Xsand_stonesand_4, FALSE, FALSE,
4173 EL_QUICKSAND_FULL, -1, -1
4176 Xsand_stoneout_1, FALSE, FALSE,
4177 EL_ROCK, ACTION_EMPTYING, -1
4180 Xsand_stoneout_2, FALSE, FALSE,
4181 EL_ROCK, ACTION_EMPTYING, -1
4184 Xsand_sandstone_1, FALSE, FALSE,
4185 EL_QUICKSAND_FULL, -1, -1
4188 Xsand_sandstone_2, FALSE, FALSE,
4189 EL_QUICKSAND_FULL, -1, -1
4192 Xsand_sandstone_3, FALSE, FALSE,
4193 EL_QUICKSAND_FULL, -1, -1
4196 Xsand_sandstone_4, FALSE, FALSE,
4197 EL_QUICKSAND_FULL, -1, -1
4200 Xplant, TRUE, FALSE,
4201 EL_EMC_PLANT, -1, -1
4204 Yplant, FALSE, FALSE,
4205 EL_EMC_PLANT, -1, -1
4208 Xlenses, TRUE, FALSE,
4209 EL_EMC_LENSES, -1, -1
4212 Xmagnify, TRUE, FALSE,
4213 EL_EMC_MAGNIFIER, -1, -1
4216 Xdripper, TRUE, FALSE,
4217 EL_EMC_DRIPPER, -1, -1
4220 XdripperB, FALSE, FALSE,
4221 EL_EMC_DRIPPER, ACTION_ACTIVE, -1
4224 Xfake_blank, TRUE, FALSE,
4225 EL_INVISIBLE_WALL, -1, -1
4228 Xfake_blankB, FALSE, FALSE,
4229 EL_INVISIBLE_WALL, ACTION_ACTIVE, -1
4232 Xfake_grass, TRUE, FALSE,
4233 EL_EMC_FAKE_GRASS, -1, -1
4236 Xfake_grassB, FALSE, FALSE,
4237 EL_EMC_FAKE_GRASS, ACTION_ACTIVE, -1
4240 Xfake_door_1, TRUE, FALSE,
4241 EL_EM_GATE_1_GRAY, -1, -1
4244 Xfake_door_2, TRUE, FALSE,
4245 EL_EM_GATE_2_GRAY, -1, -1
4248 Xfake_door_3, TRUE, FALSE,
4249 EL_EM_GATE_3_GRAY, -1, -1
4252 Xfake_door_4, TRUE, FALSE,
4253 EL_EM_GATE_4_GRAY, -1, -1
4256 Xfake_door_5, TRUE, FALSE,
4257 EL_EMC_GATE_5_GRAY, -1, -1
4260 Xfake_door_6, TRUE, FALSE,
4261 EL_EMC_GATE_6_GRAY, -1, -1
4264 Xfake_door_7, TRUE, FALSE,
4265 EL_EMC_GATE_7_GRAY, -1, -1
4268 Xfake_door_8, TRUE, FALSE,
4269 EL_EMC_GATE_8_GRAY, -1, -1
4272 Xfake_acid_1, TRUE, FALSE,
4273 EL_EMC_FAKE_ACID, -1, -1
4276 Xfake_acid_2, FALSE, FALSE,
4277 EL_EMC_FAKE_ACID, -1, -1
4280 Xfake_acid_3, FALSE, FALSE,
4281 EL_EMC_FAKE_ACID, -1, -1
4284 Xfake_acid_4, FALSE, FALSE,
4285 EL_EMC_FAKE_ACID, -1, -1
4288 Xfake_acid_5, FALSE, FALSE,
4289 EL_EMC_FAKE_ACID, -1, -1
4292 Xfake_acid_6, FALSE, FALSE,
4293 EL_EMC_FAKE_ACID, -1, -1
4296 Xfake_acid_7, FALSE, FALSE,
4297 EL_EMC_FAKE_ACID, -1, -1
4300 Xfake_acid_8, FALSE, FALSE,
4301 EL_EMC_FAKE_ACID, -1, -1
4304 Xsteel_1, TRUE, FALSE,
4305 EL_STEELWALL, -1, -1
4308 Xsteel_2, TRUE, FALSE,
4309 EL_EMC_STEELWALL_2, -1, -1
4312 Xsteel_3, TRUE, FALSE,
4313 EL_EMC_STEELWALL_3, -1, -1
4316 Xsteel_4, TRUE, FALSE,
4317 EL_EMC_STEELWALL_4, -1, -1
4320 Xwall_1, TRUE, FALSE,
4324 Xwall_2, TRUE, FALSE,
4325 EL_EMC_WALL_14, -1, -1
4328 Xwall_3, TRUE, FALSE,
4329 EL_EMC_WALL_15, -1, -1
4332 Xwall_4, TRUE, FALSE,
4333 EL_EMC_WALL_16, -1, -1
4336 Xround_wall_1, TRUE, FALSE,
4337 EL_WALL_SLIPPERY, -1, -1
4340 Xround_wall_2, TRUE, FALSE,
4341 EL_EMC_WALL_SLIPPERY_2, -1, -1
4344 Xround_wall_3, TRUE, FALSE,
4345 EL_EMC_WALL_SLIPPERY_3, -1, -1
4348 Xround_wall_4, TRUE, FALSE,
4349 EL_EMC_WALL_SLIPPERY_4, -1, -1
4352 Xdecor_1, TRUE, FALSE,
4353 EL_EMC_WALL_8, -1, -1
4356 Xdecor_2, TRUE, FALSE,
4357 EL_EMC_WALL_6, -1, -1
4360 Xdecor_3, TRUE, FALSE,
4361 EL_EMC_WALL_4, -1, -1
4364 Xdecor_4, TRUE, FALSE,
4365 EL_EMC_WALL_7, -1, -1
4368 Xdecor_5, TRUE, FALSE,
4369 EL_EMC_WALL_5, -1, -1
4372 Xdecor_6, TRUE, FALSE,
4373 EL_EMC_WALL_9, -1, -1
4376 Xdecor_7, TRUE, FALSE,
4377 EL_EMC_WALL_10, -1, -1
4380 Xdecor_8, TRUE, FALSE,
4381 EL_EMC_WALL_1, -1, -1
4384 Xdecor_9, TRUE, FALSE,
4385 EL_EMC_WALL_2, -1, -1
4388 Xdecor_10, TRUE, FALSE,
4389 EL_EMC_WALL_3, -1, -1
4392 Xdecor_11, TRUE, FALSE,
4393 EL_EMC_WALL_11, -1, -1
4396 Xdecor_12, TRUE, FALSE,
4397 EL_EMC_WALL_12, -1, -1
4400 Xalpha_0, TRUE, FALSE,
4401 EL_CHAR('0'), -1, -1
4404 Xalpha_1, TRUE, FALSE,
4405 EL_CHAR('1'), -1, -1
4408 Xalpha_2, TRUE, FALSE,
4409 EL_CHAR('2'), -1, -1
4412 Xalpha_3, TRUE, FALSE,
4413 EL_CHAR('3'), -1, -1
4416 Xalpha_4, TRUE, FALSE,
4417 EL_CHAR('4'), -1, -1
4420 Xalpha_5, TRUE, FALSE,
4421 EL_CHAR('5'), -1, -1
4424 Xalpha_6, TRUE, FALSE,
4425 EL_CHAR('6'), -1, -1
4428 Xalpha_7, TRUE, FALSE,
4429 EL_CHAR('7'), -1, -1
4432 Xalpha_8, TRUE, FALSE,
4433 EL_CHAR('8'), -1, -1
4436 Xalpha_9, TRUE, FALSE,
4437 EL_CHAR('9'), -1, -1
4440 Xalpha_excla, TRUE, FALSE,
4441 EL_CHAR('!'), -1, -1
4444 Xalpha_quote, TRUE, FALSE,
4445 EL_CHAR('"'), -1, -1
4448 Xalpha_comma, TRUE, FALSE,
4449 EL_CHAR(','), -1, -1
4452 Xalpha_minus, TRUE, FALSE,
4453 EL_CHAR('-'), -1, -1
4456 Xalpha_perio, TRUE, FALSE,
4457 EL_CHAR('.'), -1, -1
4460 Xalpha_colon, TRUE, FALSE,
4461 EL_CHAR(':'), -1, -1
4464 Xalpha_quest, TRUE, FALSE,
4465 EL_CHAR('?'), -1, -1
4468 Xalpha_a, TRUE, FALSE,
4469 EL_CHAR('A'), -1, -1
4472 Xalpha_b, TRUE, FALSE,
4473 EL_CHAR('B'), -1, -1
4476 Xalpha_c, TRUE, FALSE,
4477 EL_CHAR('C'), -1, -1
4480 Xalpha_d, TRUE, FALSE,
4481 EL_CHAR('D'), -1, -1
4484 Xalpha_e, TRUE, FALSE,
4485 EL_CHAR('E'), -1, -1
4488 Xalpha_f, TRUE, FALSE,
4489 EL_CHAR('F'), -1, -1
4492 Xalpha_g, TRUE, FALSE,
4493 EL_CHAR('G'), -1, -1
4496 Xalpha_h, TRUE, FALSE,
4497 EL_CHAR('H'), -1, -1
4500 Xalpha_i, TRUE, FALSE,
4501 EL_CHAR('I'), -1, -1
4504 Xalpha_j, TRUE, FALSE,
4505 EL_CHAR('J'), -1, -1
4508 Xalpha_k, TRUE, FALSE,
4509 EL_CHAR('K'), -1, -1
4512 Xalpha_l, TRUE, FALSE,
4513 EL_CHAR('L'), -1, -1
4516 Xalpha_m, TRUE, FALSE,
4517 EL_CHAR('M'), -1, -1
4520 Xalpha_n, TRUE, FALSE,
4521 EL_CHAR('N'), -1, -1
4524 Xalpha_o, TRUE, FALSE,
4525 EL_CHAR('O'), -1, -1
4528 Xalpha_p, TRUE, FALSE,
4529 EL_CHAR('P'), -1, -1
4532 Xalpha_q, TRUE, FALSE,
4533 EL_CHAR('Q'), -1, -1
4536 Xalpha_r, TRUE, FALSE,
4537 EL_CHAR('R'), -1, -1
4540 Xalpha_s, TRUE, FALSE,
4541 EL_CHAR('S'), -1, -1
4544 Xalpha_t, TRUE, FALSE,
4545 EL_CHAR('T'), -1, -1
4548 Xalpha_u, TRUE, FALSE,
4549 EL_CHAR('U'), -1, -1
4552 Xalpha_v, TRUE, FALSE,
4553 EL_CHAR('V'), -1, -1
4556 Xalpha_w, TRUE, FALSE,
4557 EL_CHAR('W'), -1, -1
4560 Xalpha_x, TRUE, FALSE,
4561 EL_CHAR('X'), -1, -1
4564 Xalpha_y, TRUE, FALSE,
4565 EL_CHAR('Y'), -1, -1
4568 Xalpha_z, TRUE, FALSE,
4569 EL_CHAR('Z'), -1, -1
4572 Xalpha_arrow_e, TRUE, FALSE,
4573 EL_CHAR('>'), -1, -1
4576 Xalpha_arrow_w, TRUE, FALSE,
4577 EL_CHAR('<'), -1, -1
4580 Xalpha_copyr, TRUE, FALSE,
4581 EL_CHAR('©'), -1, -1
4584 Xalpha_copyr, TRUE, FALSE,
4585 EL_CHAR('©'), -1, -1
4589 Xboom_bug, FALSE, FALSE,
4590 EL_BUG, ACTION_EXPLODING, -1
4593 Xboom_bomb, FALSE, FALSE,
4594 EL_BOMB, ACTION_EXPLODING, -1
4597 Xboom_android, FALSE, FALSE,
4598 EL_EMC_ANDROID, ACTION_OTHER, -1
4601 Xboom_1, FALSE, FALSE,
4602 EL_DEFAULT, ACTION_EXPLODING, -1
4605 Xboom_2, FALSE, FALSE,
4606 EL_DEFAULT, ACTION_EXPLODING, -1
4609 Znormal, FALSE, FALSE,
4613 Zdynamite, FALSE, FALSE,
4617 Zplayer, FALSE, FALSE,
4621 ZBORDER, FALSE, FALSE,
4631 static struct Mapping_EM_to_RND_player
4640 em_player_mapping_list[] =
4644 EL_PLAYER_1, ACTION_MOVING, MV_BIT_UP,
4648 EL_PLAYER_1, ACTION_MOVING, MV_BIT_RIGHT,
4652 EL_PLAYER_1, ACTION_MOVING, MV_BIT_DOWN,
4656 EL_PLAYER_1, ACTION_MOVING, MV_BIT_LEFT,
4660 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_UP,
4664 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_RIGHT,
4668 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_DOWN,
4672 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_LEFT,
4676 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_UP,
4680 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_RIGHT,
4684 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_DOWN,
4688 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_LEFT,
4692 EL_PLAYER_2, ACTION_MOVING, MV_BIT_UP,
4696 EL_PLAYER_2, ACTION_MOVING, MV_BIT_RIGHT,
4700 EL_PLAYER_2, ACTION_MOVING, MV_BIT_DOWN,
4704 EL_PLAYER_2, ACTION_MOVING, MV_BIT_LEFT,
4708 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_UP,
4712 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_RIGHT,
4716 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_DOWN,
4720 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_LEFT,
4724 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_UP,
4728 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_RIGHT,
4732 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_DOWN,
4736 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_LEFT,
4740 EL_PLAYER_1, ACTION_DEFAULT, -1,
4744 EL_PLAYER_2, ACTION_DEFAULT, -1,
4748 EL_PLAYER_3, ACTION_MOVING, MV_BIT_UP,
4752 EL_PLAYER_3, ACTION_MOVING, MV_BIT_RIGHT,
4756 EL_PLAYER_3, ACTION_MOVING, MV_BIT_DOWN,
4760 EL_PLAYER_3, ACTION_MOVING, MV_BIT_LEFT,
4764 EL_PLAYER_3, ACTION_PUSHING, MV_BIT_UP,
4768 EL_PLAYER_3, ACTION_PUSHING, MV_BIT_RIGHT,
4772 EL_PLAYER_3, ACTION_PUSHING, MV_BIT_DOWN,
4776 EL_PLAYER_3, ACTION_PUSHING, MV_BIT_LEFT,
4780 EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_UP,
4784 EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_RIGHT,
4788 EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_DOWN,
4792 EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_LEFT,
4796 EL_PLAYER_4, ACTION_MOVING, MV_BIT_UP,
4800 EL_PLAYER_4, ACTION_MOVING, MV_BIT_RIGHT,
4804 EL_PLAYER_4, ACTION_MOVING, MV_BIT_DOWN,
4808 EL_PLAYER_4, ACTION_MOVING, MV_BIT_LEFT,
4812 EL_PLAYER_4, ACTION_PUSHING, MV_BIT_UP,
4816 EL_PLAYER_4, ACTION_PUSHING, MV_BIT_RIGHT,
4820 EL_PLAYER_4, ACTION_PUSHING, MV_BIT_DOWN,
4824 EL_PLAYER_4, ACTION_PUSHING, MV_BIT_LEFT,
4828 EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_UP,
4832 EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_RIGHT,
4836 EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_DOWN,
4840 EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_LEFT,
4844 EL_PLAYER_3, ACTION_DEFAULT, -1,
4848 EL_PLAYER_4, ACTION_DEFAULT, -1,
4857 int map_element_RND_to_EM(int element_rnd)
4859 static unsigned short mapping_RND_to_EM[NUM_FILE_ELEMENTS];
4860 static boolean mapping_initialized = FALSE;
4862 if (!mapping_initialized)
4866 /* return "Xalpha_quest" for all undefined elements in mapping array */
4867 for (i = 0; i < NUM_FILE_ELEMENTS; i++)
4868 mapping_RND_to_EM[i] = Xalpha_quest;
4870 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
4871 if (em_object_mapping_list[i].is_rnd_to_em_mapping)
4872 mapping_RND_to_EM[em_object_mapping_list[i].element_rnd] =
4873 em_object_mapping_list[i].element_em;
4875 mapping_initialized = TRUE;
4878 if (element_rnd >= 0 && element_rnd < NUM_FILE_ELEMENTS)
4879 return mapping_RND_to_EM[element_rnd];
4881 Error(ERR_WARN, "invalid RND level element %d", element_rnd);
4886 int map_element_EM_to_RND(int element_em)
4888 static unsigned short mapping_EM_to_RND[TILE_MAX];
4889 static boolean mapping_initialized = FALSE;
4891 if (!mapping_initialized)
4895 /* return "EL_UNKNOWN" for all undefined elements in mapping array */
4896 for (i = 0; i < TILE_MAX; i++)
4897 mapping_EM_to_RND[i] = EL_UNKNOWN;
4899 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
4900 mapping_EM_to_RND[em_object_mapping_list[i].element_em] =
4901 em_object_mapping_list[i].element_rnd;
4903 mapping_initialized = TRUE;
4906 if (element_em >= 0 && element_em < TILE_MAX)
4907 return mapping_EM_to_RND[element_em];
4909 Error(ERR_WARN, "invalid EM level element %d", element_em);
4914 void map_android_clone_elements_RND_to_EM(struct LevelInfo *level)
4916 struct LevelInfo_EM *level_em = level->native_em_level;
4917 struct LEVEL *lev = level_em->lev;
4920 for (i = 0; i < TILE_MAX; i++)
4921 lev->android_array[i] = Xblank;
4923 for (i = 0; i < level->num_android_clone_elements; i++)
4925 int element_rnd = level->android_clone_element[i];
4926 int element_em = map_element_RND_to_EM(element_rnd);
4928 for (j = 0; em_object_mapping_list[j].element_em != -1; j++)
4929 if (em_object_mapping_list[j].element_rnd == element_rnd)
4930 lev->android_array[em_object_mapping_list[j].element_em] = element_em;
4934 void map_android_clone_elements_EM_to_RND(struct LevelInfo *level)
4936 struct LevelInfo_EM *level_em = level->native_em_level;
4937 struct LEVEL *lev = level_em->lev;
4940 level->num_android_clone_elements = 0;
4942 for (i = 0; i < TILE_MAX; i++)
4944 int element_em = lev->android_array[i];
4946 boolean element_found = FALSE;
4948 if (element_em == Xblank)
4951 element_rnd = map_element_EM_to_RND(element_em);
4953 for (j = 0; j < level->num_android_clone_elements; j++)
4954 if (level->android_clone_element[j] == element_rnd)
4955 element_found = TRUE;
4959 level->android_clone_element[level->num_android_clone_elements++] =
4962 if (level->num_android_clone_elements == MAX_ANDROID_ELEMENTS)
4967 if (level->num_android_clone_elements == 0)
4969 level->num_android_clone_elements = 1;
4970 level->android_clone_element[0] = EL_EMPTY;
4974 int map_direction_RND_to_EM(int direction)
4976 return (direction == MV_UP ? 0 :
4977 direction == MV_RIGHT ? 1 :
4978 direction == MV_DOWN ? 2 :
4979 direction == MV_LEFT ? 3 :
4983 int map_direction_EM_to_RND(int direction)
4985 return (direction == 0 ? MV_UP :
4986 direction == 1 ? MV_RIGHT :
4987 direction == 2 ? MV_DOWN :
4988 direction == 3 ? MV_LEFT :
4992 int get_next_element(int element)
4996 case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL;
4997 case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY;
4998 case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL;
4999 case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_ACTIVE;
5000 case EL_BD_MAGIC_WALL_FILLING: return EL_BD_MAGIC_WALL_FULL;
5001 case EL_BD_MAGIC_WALL_EMPTYING: return EL_BD_MAGIC_WALL_ACTIVE;
5002 case EL_AMOEBA_DROPPING: return EL_AMOEBA_WET;
5004 default: return element;
5009 int el_act_dir2img(int element, int action, int direction)
5011 element = GFX_ELEMENT(element);
5013 if (direction == MV_NONE)
5014 return element_info[element].graphic[action];
5016 direction = MV_DIR_TO_BIT(direction);
5018 return element_info[element].direction_graphic[action][direction];
5021 int el_act_dir2img(int element, int action, int direction)
5023 element = GFX_ELEMENT(element);
5024 direction = MV_DIR_TO_BIT(direction); /* default: MV_NONE => MV_DOWN */
5026 /* direction_graphic[][] == graphic[] for undefined direction graphics */
5027 return element_info[element].direction_graphic[action][direction];
5032 static int el_act_dir2crm(int element, int action, int direction)
5034 element = GFX_ELEMENT(element);
5036 if (direction == MV_NONE)
5037 return element_info[element].crumbled[action];
5039 direction = MV_DIR_TO_BIT(direction);
5041 return element_info[element].direction_crumbled[action][direction];
5044 static int el_act_dir2crm(int element, int action, int direction)
5046 element = GFX_ELEMENT(element);
5047 direction = MV_DIR_TO_BIT(direction); /* default: MV_NONE => MV_DOWN */
5049 /* direction_graphic[][] == graphic[] for undefined direction graphics */
5050 return element_info[element].direction_crumbled[action][direction];
5054 int el_act2img(int element, int action)
5056 element = GFX_ELEMENT(element);
5058 return element_info[element].graphic[action];
5061 int el_act2crm(int element, int action)
5063 element = GFX_ELEMENT(element);
5065 return element_info[element].crumbled[action];
5068 int el_dir2img(int element, int direction)
5070 element = GFX_ELEMENT(element);
5072 return el_act_dir2img(element, ACTION_DEFAULT, direction);
5075 int el2baseimg(int element)
5077 return element_info[element].graphic[ACTION_DEFAULT];
5080 int el2img(int element)
5082 element = GFX_ELEMENT(element);
5084 return element_info[element].graphic[ACTION_DEFAULT];
5087 int el2edimg(int element)
5089 element = GFX_ELEMENT(element);
5091 return element_info[element].special_graphic[GFX_SPECIAL_ARG_EDITOR];
5094 int el2preimg(int element)
5096 element = GFX_ELEMENT(element);
5098 return element_info[element].special_graphic[GFX_SPECIAL_ARG_PREVIEW];
5101 int font2baseimg(int font_nr)
5103 return font_info[font_nr].special_graphic[GFX_SPECIAL_ARG_DEFAULT];
5106 int getGameFrameDelay_EM(int native_em_game_frame_delay)
5108 int game_frame_delay_value;
5110 game_frame_delay_value =
5111 (tape.playing && tape.fast_forward ? FfwdFrameDelay :
5112 GameFrameDelay == GAME_FRAME_DELAY ? native_em_game_frame_delay :
5115 if (tape.playing && tape.warp_forward && !tape.pausing)
5116 game_frame_delay_value = 0;
5118 return game_frame_delay_value;
5121 unsigned int InitRND(long seed)
5123 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
5124 return InitEngineRND_EM(seed);
5126 return InitEngineRND(seed);
5129 #define DEBUG_EM_GFX 0
5131 void InitGraphicInfo_EM(void)
5133 struct Mapping_EM_to_RND_object object_mapping[TILE_MAX];
5134 struct Mapping_EM_to_RND_player player_mapping[MAX_PLAYERS][SPR_MAX];
5138 if (graphic_info_em_object[0][0].bitmap == NULL)
5140 /* EM graphics not yet initialized in em_open_all() */
5146 /* always start with reliable default values */
5147 for (i = 0; i < TILE_MAX; i++)
5149 object_mapping[i].element_rnd = EL_UNKNOWN;
5150 object_mapping[i].is_backside = FALSE;
5151 object_mapping[i].action = ACTION_DEFAULT;
5152 object_mapping[i].direction = MV_NONE;
5155 /* always start with reliable default values */
5156 for (p = 0; p < MAX_PLAYERS; p++)
5158 for (i = 0; i < SPR_MAX; i++)
5160 player_mapping[p][i].element_rnd = EL_UNKNOWN;
5161 player_mapping[p][i].action = ACTION_DEFAULT;
5162 player_mapping[p][i].direction = MV_NONE;
5166 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
5168 int e = em_object_mapping_list[i].element_em;
5170 object_mapping[e].element_rnd = em_object_mapping_list[i].element_rnd;
5171 object_mapping[e].is_backside = em_object_mapping_list[i].is_backside;
5173 if (em_object_mapping_list[i].action != -1)
5174 object_mapping[e].action = em_object_mapping_list[i].action;
5176 if (em_object_mapping_list[i].direction != -1)
5177 object_mapping[e].direction =
5178 MV_DIR_FROM_BIT(em_object_mapping_list[i].direction);
5181 for (i = 0; em_player_mapping_list[i].action_em != -1; i++)
5183 int a = em_player_mapping_list[i].action_em;
5184 int p = em_player_mapping_list[i].player_nr;
5186 player_mapping[p][a].element_rnd = em_player_mapping_list[i].element_rnd;
5188 if (em_player_mapping_list[i].action != -1)
5189 player_mapping[p][a].action = em_player_mapping_list[i].action;
5191 if (em_player_mapping_list[i].direction != -1)
5192 player_mapping[p][a].direction =
5193 MV_DIR_FROM_BIT(em_player_mapping_list[i].direction);
5196 for (i = 0; i < TILE_MAX; i++)
5198 int element = object_mapping[i].element_rnd;
5199 int action = object_mapping[i].action;
5200 int direction = object_mapping[i].direction;
5201 boolean is_backside = object_mapping[i].is_backside;
5202 boolean action_removing = (action == ACTION_DIGGING ||
5203 action == ACTION_SNAPPING ||
5204 action == ACTION_COLLECTING);
5205 boolean action_exploding = ((action == ACTION_EXPLODING ||
5206 action == ACTION_SMASHED_BY_ROCK ||
5207 action == ACTION_SMASHED_BY_SPRING) &&
5208 element != EL_DIAMOND);
5209 boolean action_active = (action == ACTION_ACTIVE);
5210 boolean action_other = (action == ACTION_OTHER);
5212 for (j = 0; j < 8; j++)
5214 int effective_element = (j > 5 && i == Yacid_splash_eB ? EL_EMPTY :
5215 j > 5 && i == Yacid_splash_wB ? EL_EMPTY :
5217 i == Xdrip_stretch ? element :
5218 i == Xdrip_stretchB ? element :
5219 i == Ydrip_s1 ? element :
5220 i == Ydrip_s1B ? element :
5221 i == Xball_1B ? element :
5222 i == Xball_2 ? element :
5223 i == Xball_2B ? element :
5224 i == Yball_eat ? element :
5225 i == Ykey_1_eat ? element :
5226 i == Ykey_2_eat ? element :
5227 i == Ykey_3_eat ? element :
5228 i == Ykey_4_eat ? element :
5229 i == Ykey_5_eat ? element :
5230 i == Ykey_6_eat ? element :
5231 i == Ykey_7_eat ? element :
5232 i == Ykey_8_eat ? element :
5233 i == Ylenses_eat ? element :
5234 i == Ymagnify_eat ? element :
5235 i == Ygrass_eat ? element :
5236 i == Ydirt_eat ? element :
5237 i == Yspring_kill_e ? EL_SPRING :
5238 i == Yspring_kill_w ? EL_SPRING :
5239 i == Yemerald_stone ? EL_EMERALD :
5240 i == Ydiamond_stone ? EL_ROCK :
5241 i == Xsand_stonein_4 ? EL_EMPTY :
5242 i == Xsand_stoneout_2 ? EL_ROCK :
5243 is_backside ? EL_EMPTY :
5244 action_removing ? EL_EMPTY :
5246 int effective_action = (j < 7 ? action :
5247 i == Xdrip_stretch ? action :
5248 i == Xdrip_stretchB ? action :
5249 i == Ydrip_s1 ? action :
5250 i == Ydrip_s1B ? action :
5251 i == Xball_1B ? action :
5252 i == Xball_2 ? action :
5253 i == Xball_2B ? action :
5254 i == Yball_eat ? action :
5255 i == Ykey_1_eat ? action :
5256 i == Ykey_2_eat ? action :
5257 i == Ykey_3_eat ? action :
5258 i == Ykey_4_eat ? action :
5259 i == Ykey_5_eat ? action :
5260 i == Ykey_6_eat ? action :
5261 i == Ykey_7_eat ? action :
5262 i == Ykey_8_eat ? action :
5263 i == Ylenses_eat ? action :
5264 i == Ymagnify_eat ? action :
5265 i == Ygrass_eat ? action :
5266 i == Ydirt_eat ? action :
5267 i == Xsand_stonein_1 ? action :
5268 i == Xsand_stonein_2 ? action :
5269 i == Xsand_stonein_3 ? action :
5270 i == Xsand_stonein_4 ? action :
5271 i == Xsand_stoneout_1 ? action :
5272 i == Xsand_stoneout_2 ? action :
5273 i == Xboom_android ? ACTION_EXPLODING :
5274 action_exploding ? ACTION_EXPLODING :
5275 action_active ? action :
5276 action_other ? action :
5278 int graphic = (el_act_dir2img(effective_element, effective_action,
5280 int crumbled = (el_act_dir2crm(effective_element, effective_action,
5282 int base_graphic = el_act2img(effective_element, ACTION_DEFAULT);
5283 int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT);
5284 boolean has_crumbled_graphics = (base_crumbled != base_graphic);
5285 struct GraphicInfo *g = &graphic_info[graphic];
5286 struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
5289 /* ensure to get symmetric 3-frame, 2-delay animations as used in EM */
5290 boolean special_animation = (action != ACTION_DEFAULT &&
5291 g->anim_frames == 3 &&
5292 g->anim_delay == 2 &&
5293 g->anim_mode & ANIM_LINEAR);
5294 int sync_frame = (i == Xdrip_stretch ? 7 :
5295 i == Xdrip_stretchB ? 7 :
5296 i == Ydrip_s2 ? j + 8 :
5297 i == Ydrip_s2B ? j + 8 :
5306 i == Xfake_acid_1 ? 0 :
5307 i == Xfake_acid_2 ? 10 :
5308 i == Xfake_acid_3 ? 20 :
5309 i == Xfake_acid_4 ? 30 :
5310 i == Xfake_acid_5 ? 40 :
5311 i == Xfake_acid_6 ? 50 :
5312 i == Xfake_acid_7 ? 60 :
5313 i == Xfake_acid_8 ? 70 :
5315 i == Xball_2B ? j + 8 :
5316 i == Yball_eat ? j + 1 :
5317 i == Ykey_1_eat ? j + 1 :
5318 i == Ykey_2_eat ? j + 1 :
5319 i == Ykey_3_eat ? j + 1 :
5320 i == Ykey_4_eat ? j + 1 :
5321 i == Ykey_5_eat ? j + 1 :
5322 i == Ykey_6_eat ? j + 1 :
5323 i == Ykey_7_eat ? j + 1 :
5324 i == Ykey_8_eat ? j + 1 :
5325 i == Ylenses_eat ? j + 1 :
5326 i == Ymagnify_eat ? j + 1 :
5327 i == Ygrass_eat ? j + 1 :
5328 i == Ydirt_eat ? j + 1 :
5329 i == Xamoeba_1 ? 0 :
5330 i == Xamoeba_2 ? 1 :
5331 i == Xamoeba_3 ? 2 :
5332 i == Xamoeba_4 ? 3 :
5333 i == Xamoeba_5 ? 0 :
5334 i == Xamoeba_6 ? 1 :
5335 i == Xamoeba_7 ? 2 :
5336 i == Xamoeba_8 ? 3 :
5337 i == Xexit_2 ? j + 8 :
5338 i == Xexit_3 ? j + 16 :
5339 i == Xdynamite_1 ? 0 :
5340 i == Xdynamite_2 ? 8 :
5341 i == Xdynamite_3 ? 16 :
5342 i == Xdynamite_4 ? 24 :
5343 i == Xsand_stonein_1 ? j + 1 :
5344 i == Xsand_stonein_2 ? j + 9 :
5345 i == Xsand_stonein_3 ? j + 17 :
5346 i == Xsand_stonein_4 ? j + 25 :
5347 i == Xsand_stoneout_1 && j == 0 ? 0 :
5348 i == Xsand_stoneout_1 && j == 1 ? 0 :
5349 i == Xsand_stoneout_1 && j == 2 ? 1 :
5350 i == Xsand_stoneout_1 && j == 3 ? 2 :
5351 i == Xsand_stoneout_1 && j == 4 ? 2 :
5352 i == Xsand_stoneout_1 && j == 5 ? 3 :
5353 i == Xsand_stoneout_1 && j == 6 ? 4 :
5354 i == Xsand_stoneout_1 && j == 7 ? 4 :
5355 i == Xsand_stoneout_2 && j == 0 ? 5 :
5356 i == Xsand_stoneout_2 && j == 1 ? 6 :
5357 i == Xsand_stoneout_2 && j == 2 ? 7 :
5358 i == Xsand_stoneout_2 && j == 3 ? 8 :
5359 i == Xsand_stoneout_2 && j == 4 ? 9 :
5360 i == Xsand_stoneout_2 && j == 5 ? 11 :
5361 i == Xsand_stoneout_2 && j == 6 ? 13 :
5362 i == Xsand_stoneout_2 && j == 7 ? 15 :
5363 i == Xboom_bug && j == 1 ? 2 :
5364 i == Xboom_bug && j == 2 ? 2 :
5365 i == Xboom_bug && j == 3 ? 4 :
5366 i == Xboom_bug && j == 4 ? 4 :
5367 i == Xboom_bug && j == 5 ? 2 :
5368 i == Xboom_bug && j == 6 ? 2 :
5369 i == Xboom_bug && j == 7 ? 0 :
5370 i == Xboom_bomb && j == 1 ? 2 :
5371 i == Xboom_bomb && j == 2 ? 2 :
5372 i == Xboom_bomb && j == 3 ? 4 :
5373 i == Xboom_bomb && j == 4 ? 4 :
5374 i == Xboom_bomb && j == 5 ? 2 :
5375 i == Xboom_bomb && j == 6 ? 2 :
5376 i == Xboom_bomb && j == 7 ? 0 :
5377 i == Xboom_android && j == 7 ? 6 :
5378 i == Xboom_1 && j == 1 ? 2 :
5379 i == Xboom_1 && j == 2 ? 2 :
5380 i == Xboom_1 && j == 3 ? 4 :
5381 i == Xboom_1 && j == 4 ? 4 :
5382 i == Xboom_1 && j == 5 ? 6 :
5383 i == Xboom_1 && j == 6 ? 6 :
5384 i == Xboom_1 && j == 7 ? 8 :
5385 i == Xboom_2 && j == 0 ? 8 :
5386 i == Xboom_2 && j == 1 ? 8 :
5387 i == Xboom_2 && j == 2 ? 10 :
5388 i == Xboom_2 && j == 3 ? 10 :
5389 i == Xboom_2 && j == 4 ? 10 :
5390 i == Xboom_2 && j == 5 ? 12 :
5391 i == Xboom_2 && j == 6 ? 12 :
5392 i == Xboom_2 && j == 7 ? 12 :
5393 special_animation && j == 4 ? 3 :
5394 effective_action != action ? 0 :
5398 Bitmap *debug_bitmap = g_em->bitmap;
5399 int debug_src_x = g_em->src_x;
5400 int debug_src_y = g_em->src_y;
5403 int frame = getAnimationFrame(g->anim_frames,
5406 g->anim_start_frame,
5409 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y,
5410 g->double_movement && is_backside);
5412 g_em->bitmap = src_bitmap;
5413 g_em->src_x = src_x;
5414 g_em->src_y = src_y;
5415 g_em->src_offset_x = 0;
5416 g_em->src_offset_y = 0;
5417 g_em->dst_offset_x = 0;
5418 g_em->dst_offset_y = 0;
5419 g_em->width = TILEX;
5420 g_em->height = TILEY;
5422 g_em->crumbled_bitmap = NULL;
5423 g_em->crumbled_src_x = 0;
5424 g_em->crumbled_src_y = 0;
5425 g_em->crumbled_border_size = 0;
5427 g_em->has_crumbled_graphics = FALSE;
5428 g_em->preserve_background = FALSE;
5431 if (has_crumbled_graphics && crumbled == IMG_EMPTY_SPACE)
5432 printf("::: empty crumbled: %d [%s], %d, %d\n",
5433 effective_element, element_info[effective_element].token_name,
5434 effective_action, direction);
5437 /* if element can be crumbled, but certain action graphics are just empty
5438 space (like snapping sand with the original R'n'D graphics), do not
5439 treat these empty space graphics as crumbled graphics in EMC engine */
5440 if (has_crumbled_graphics && crumbled != IMG_EMPTY_SPACE)
5442 getGraphicSource(crumbled, frame, &src_bitmap, &src_x, &src_y);
5444 g_em->has_crumbled_graphics = TRUE;
5445 g_em->crumbled_bitmap = src_bitmap;
5446 g_em->crumbled_src_x = src_x;
5447 g_em->crumbled_src_y = src_y;
5448 g_em->crumbled_border_size = graphic_info[crumbled].border_size;
5451 if (!g->double_movement && (effective_action == ACTION_FALLING ||
5452 effective_action == ACTION_MOVING ||
5453 effective_action == ACTION_PUSHING ||
5454 effective_action == ACTION_EATING))
5457 (effective_action == ACTION_FALLING ? MV_DOWN : direction);
5458 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? 1 : 0);
5459 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? 1 : 0);
5460 int num_steps = (i == Ydrip_s1 ||
5463 i == Ydrip_s2B ? 16 : 8);
5464 int cx = ABS(dx) * (TILEX / num_steps);
5465 int cy = ABS(dy) * (TILEY / num_steps);
5466 int step_frame = (i == Ydrip_s2 ||
5467 i == Ydrip_s2B ? j + 8 : j) + 1;
5468 int step = (is_backside ? step_frame : num_steps - step_frame);
5470 if (is_backside) /* tile where movement starts */
5472 if (dx < 0 || dy < 0)
5474 g_em->src_offset_x = cx * step;
5475 g_em->src_offset_y = cy * step;
5479 g_em->dst_offset_x = cx * step;
5480 g_em->dst_offset_y = cy * step;
5483 else /* tile where movement ends */
5485 if (dx < 0 || dy < 0)
5487 g_em->dst_offset_x = cx * step;
5488 g_em->dst_offset_y = cy * step;
5492 g_em->src_offset_x = cx * step;
5493 g_em->src_offset_y = cy * step;
5497 g_em->width = TILEX - cx * step;
5498 g_em->height = TILEY - cy * step;
5502 /* create unique graphic identifier to decide if tile must be redrawn */
5503 /* bit 31 - 16 (16 bit): EM style graphic
5504 bit 15 - 12 ( 4 bit): EM style frame
5505 bit 11 - 6 ( 6 bit): graphic width
5506 bit 5 - 0 ( 6 bit): graphic height */
5507 g_em->unique_identifier =
5508 (graphic << 16) | (frame << 12) | (g_em->width << 6) | g_em->height;
5510 /* create unique graphic identifier to decide if tile must be redrawn */
5511 /* bit 31 - 16 (16 bit): EM style element
5512 bit 15 - 12 ( 4 bit): EM style frame
5513 bit 11 - 6 ( 6 bit): graphic width
5514 bit 5 - 0 ( 6 bit): graphic height */
5515 g_em->unique_identifier =
5516 (i << 16) | (j << 12) | (g_em->width << 6) | g_em->height;
5520 if (effective_element == EL_ROCK)
5521 printf("::: EL_ROCK(%d, %d): %d, %d => %d\n",
5522 effective_action, j, graphic, frame, g_em->unique_identifier);
5528 /* skip check for EMC elements not contained in original EMC artwork */
5529 if (element == EL_EMC_FAKE_ACID)
5533 if (g_em->bitmap != debug_bitmap ||
5534 g_em->src_x != debug_src_x ||
5535 g_em->src_y != debug_src_y ||
5536 g_em->src_offset_x != 0 ||
5537 g_em->src_offset_y != 0 ||
5538 g_em->dst_offset_x != 0 ||
5539 g_em->dst_offset_y != 0 ||
5540 g_em->width != TILEX ||
5541 g_em->height != TILEY)
5543 static int last_i = -1;
5551 printf("::: EMC GFX ERROR for element %d -> %d ('%s', '%s', %d)",
5552 i, element, element_info[element].token_name,
5553 element_action_info[effective_action].suffix, direction);
5555 if (element != effective_element)
5556 printf(" [%d ('%s')]",
5558 element_info[effective_element].token_name);
5562 if (g_em->bitmap != debug_bitmap)
5563 printf(" %d (%d): different bitmap! (0x%08x != 0x%08x)\n",
5564 j, is_backside, (int)(g_em->bitmap), (int)(debug_bitmap));
5566 if (g_em->src_x != debug_src_x ||
5567 g_em->src_y != debug_src_y)
5568 printf(" frame %d (%c): %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
5569 j, (is_backside ? 'B' : 'F'),
5570 g_em->src_x, g_em->src_y,
5571 g_em->src_x / 32, g_em->src_y / 32,
5572 debug_src_x, debug_src_y,
5573 debug_src_x / 32, debug_src_y / 32);
5575 if (g_em->src_offset_x != 0 ||
5576 g_em->src_offset_y != 0 ||
5577 g_em->dst_offset_x != 0 ||
5578 g_em->dst_offset_y != 0)
5579 printf(" %d (%d): offsets %d,%d and %d,%d should be all 0\n",
5581 g_em->src_offset_x, g_em->src_offset_y,
5582 g_em->dst_offset_x, g_em->dst_offset_y);
5584 if (g_em->width != TILEX ||
5585 g_em->height != TILEY)
5586 printf(" %d (%d): size %d,%d should be %d,%d\n",
5588 g_em->width, g_em->height, TILEX, TILEY);
5595 for (i = 0; i < TILE_MAX; i++)
5597 for (j = 0; j < 8; j++)
5599 int element = object_mapping[i].element_rnd;
5600 int action = object_mapping[i].action;
5601 int direction = object_mapping[i].direction;
5602 boolean is_backside = object_mapping[i].is_backside;
5604 int graphic_action = el_act_dir2img(element, action, direction);
5605 int graphic_default = el_act_dir2img(element, ACTION_DEFAULT, direction);
5607 int graphic_action = element_info[element].graphic[action];
5608 int graphic_default = element_info[element].graphic[ACTION_DEFAULT];
5611 if ((action == ACTION_SMASHED_BY_ROCK ||
5612 action == ACTION_SMASHED_BY_SPRING ||
5613 action == ACTION_EATING) &&
5614 graphic_action == graphic_default)
5616 int e = (action == ACTION_SMASHED_BY_ROCK ? Ystone_s :
5617 action == ACTION_SMASHED_BY_SPRING ? Yspring_s :
5618 direction == MV_LEFT ? (is_backside? Yspring_wB: Yspring_w) :
5619 direction == MV_RIGHT ? (is_backside? Yspring_eB: Yspring_e) :
5622 /* no separate animation for "smashed by rock" -- use rock instead */
5623 struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
5624 struct GraphicInfo_EM *g_xx = &graphic_info_em_object[e][7 - j];
5626 g_em->bitmap = g_xx->bitmap;
5627 g_em->src_x = g_xx->src_x;
5628 g_em->src_y = g_xx->src_y;
5629 g_em->src_offset_x = g_xx->src_offset_x;
5630 g_em->src_offset_y = g_xx->src_offset_y;
5631 g_em->dst_offset_x = g_xx->dst_offset_x;
5632 g_em->dst_offset_y = g_xx->dst_offset_y;
5633 g_em->width = g_xx->width;
5634 g_em->height = g_xx->height;
5636 g_em->unique_identifier = g_xx->unique_identifier;
5640 g_em->preserve_background = TRUE;
5645 for (p = 0; p < MAX_PLAYERS; p++)
5647 for (i = 0; i < SPR_MAX; i++)
5649 int element = player_mapping[p][i].element_rnd;
5650 int action = player_mapping[p][i].action;
5651 int direction = player_mapping[p][i].direction;
5653 for (j = 0; j < 8; j++)
5655 int effective_element = element;
5656 int effective_action = action;
5657 int graphic = (direction == MV_NONE ?
5658 el_act2img(effective_element, effective_action) :
5659 el_act_dir2img(effective_element, effective_action,
5661 struct GraphicInfo *g = &graphic_info[graphic];
5662 struct GraphicInfo_EM *g_em = &graphic_info_em_player[p][i][7 - j];
5668 Bitmap *debug_bitmap = g_em->bitmap;
5669 int debug_src_x = g_em->src_x;
5670 int debug_src_y = g_em->src_y;
5673 int frame = getAnimationFrame(g->anim_frames,
5676 g->anim_start_frame,
5679 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x,&src_y, FALSE);
5681 g_em->bitmap = src_bitmap;
5682 g_em->src_x = src_x;
5683 g_em->src_y = src_y;
5684 g_em->src_offset_x = 0;
5685 g_em->src_offset_y = 0;
5686 g_em->dst_offset_x = 0;
5687 g_em->dst_offset_y = 0;
5688 g_em->width = TILEX;
5689 g_em->height = TILEY;
5694 /* skip check for EMC elements not contained in original EMC artwork */
5695 if (element == EL_PLAYER_3 ||
5696 element == EL_PLAYER_4)
5700 if (g_em->bitmap != debug_bitmap ||
5701 g_em->src_x != debug_src_x ||
5702 g_em->src_y != debug_src_y)
5704 static int last_i = -1;
5712 printf("::: EMC GFX ERROR for p/a %d/%d -> %d ('%s', '%s', %d)",
5713 p, i, element, element_info[element].token_name,
5714 element_action_info[effective_action].suffix, direction);
5716 if (element != effective_element)
5717 printf(" [%d ('%s')]",
5719 element_info[effective_element].token_name);
5723 if (g_em->bitmap != debug_bitmap)
5724 printf(" %d: different bitmap! (0x%08x != 0x%08x)\n",
5725 j, (int)(g_em->bitmap), (int)(debug_bitmap));
5727 if (g_em->src_x != debug_src_x ||
5728 g_em->src_y != debug_src_y)
5729 printf(" frame %d: %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
5731 g_em->src_x, g_em->src_y,
5732 g_em->src_x / 32, g_em->src_y / 32,
5733 debug_src_x, debug_src_y,
5734 debug_src_x / 32, debug_src_y / 32);