1 /***********************************************************
2 * Rocks'n'Diamonds -- McDuffin Strikes Back! *
3 *----------------------------------------------------------*
4 * (c) 1995-2002 Artsoft Entertainment *
6 * Detmolder Strasse 189 *
9 * e-mail: info@artsoft.org *
10 *----------------------------------------------------------*
12 ***********************************************************/
14 #include "libgame/libgame.h"
23 /* tool button identifiers */
24 #define TOOL_CTRL_ID_YES 0
25 #define TOOL_CTRL_ID_NO 1
26 #define TOOL_CTRL_ID_CONFIRM 2
27 #define TOOL_CTRL_ID_PLAYER_1 3
28 #define TOOL_CTRL_ID_PLAYER_2 4
29 #define TOOL_CTRL_ID_PLAYER_3 5
30 #define TOOL_CTRL_ID_PLAYER_4 6
32 #define NUM_TOOL_BUTTONS 7
34 /* forward declaration for internal use */
35 static void UnmapToolButtons();
36 static void HandleToolButtons(struct GadgetInfo *);
37 static int el_act_dir2crm(int, int, int);
38 static int el_act2crm(int, int);
40 static struct GadgetInfo *tool_gadget[NUM_TOOL_BUTTONS];
41 static int request_gadget_id = -1;
43 static char *print_if_not_empty(int element)
45 static char *s = NULL;
46 char *token_name = element_info[element].token_name;
51 s = checked_malloc(strlen(token_name) + 10 + 1);
53 if (element != EL_EMPTY)
54 sprintf(s, "%d\t['%s']", element, token_name);
56 sprintf(s, "%d", element);
61 void DumpTile(int x, int y)
67 printf("Field Info: SCREEN(%d, %d), LEVEL(%d, %d)\n", sx, sy, x, y);
70 if (!IN_LEV_FIELD(x, y))
72 printf("(not in level field)\n");
78 printf(" Feld: %d\t['%s']\n", Feld[x][y],
79 element_info[Feld[x][y]].token_name);
80 printf(" Back: %s\n", print_if_not_empty(Back[x][y]));
81 printf(" Store: %s\n", print_if_not_empty(Store[x][y]));
82 printf(" Store2: %s\n", print_if_not_empty(Store2[x][y]));
83 printf(" StorePlayer: %s\n", print_if_not_empty(StorePlayer[x][y]));
84 printf(" MovPos: %d\n", MovPos[x][y]);
85 printf(" MovDir: %d\n", MovDir[x][y]);
86 printf(" MovDelay: %d\n", MovDelay[x][y]);
87 printf(" ChangeDelay: %d\n", ChangeDelay[x][y]);
88 printf(" GfxElement: %d\n", GfxElement[x][y]);
89 printf(" GfxAction: %d\n", GfxAction[x][y]);
90 printf(" GfxFrame: %d\n", GfxFrame[x][y]);
94 void SetDrawtoField(int mode)
96 if (mode == DRAW_BUFFERED && setup.soft_scrolling)
107 drawto_field = fieldbuffer;
109 else /* DRAW_DIRECT, DRAW_BACKBUFFER */
115 BX2 = SCR_FIELDX - 1;
116 BY2 = SCR_FIELDY - 1;
120 drawto_field = (mode == DRAW_DIRECT ? window : backbuffer);
124 void RedrawPlayfield(boolean force_redraw, int x, int y, int width, int height)
126 if (game_status == GAME_MODE_PLAYING &&
127 level.game_engine_type == GAME_ENGINE_TYPE_EM)
129 BlitScreenToBitmap_EM(backbuffer);
131 else if (game_status == GAME_MODE_PLAYING && !game.envelope_active)
137 width = gfx.sxsize + 2 * TILEX;
138 height = gfx.sysize + 2 * TILEY;
141 if (force_redraw || setup.direct_draw)
144 int x1 = (x - SX) / TILEX, y1 = (y - SY) / TILEY;
145 int x2 = (x - SX + width) / TILEX, y2 = (y - SY + height) / TILEY;
147 if (setup.direct_draw)
148 SetDrawtoField(DRAW_BACKBUFFER);
150 for (xx = BX1; xx <= BX2; xx++)
151 for (yy = BY1; yy <= BY2; yy++)
152 if (xx >= x1 && xx <= x2 && yy >= y1 && yy <= y2)
153 DrawScreenField(xx, yy);
156 if (setup.direct_draw)
157 SetDrawtoField(DRAW_DIRECT);
160 if (setup.soft_scrolling)
162 int fx = FX, fy = FY;
164 fx += (ScreenMovDir & (MV_LEFT|MV_RIGHT) ? ScreenGfxPos : 0);
165 fy += (ScreenMovDir & (MV_UP|MV_DOWN) ? ScreenGfxPos : 0);
167 BlitBitmap(fieldbuffer, backbuffer, fx,fy, SXSIZE,SYSIZE, SX,SY);
171 BlitBitmap(drawto, window, x, y, width, height, x, y);
177 DrawBuffer *buffer = (drawto_field == window ? backbuffer : drawto_field);
179 if (setup.direct_draw && game_status == GAME_MODE_PLAYING)
180 redraw_mask &= ~REDRAW_MAIN;
182 if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD)
183 redraw_mask |= REDRAW_FIELD;
185 if (redraw_mask & REDRAW_FIELD)
186 redraw_mask &= ~REDRAW_TILES;
188 if (redraw_mask == REDRAW_NONE)
191 if (global.fps_slowdown && game_status == GAME_MODE_PLAYING)
193 static boolean last_frame_skipped = FALSE;
194 boolean skip_even_when_not_scrolling = TRUE;
195 boolean just_scrolling = (ScreenMovDir != 0);
196 boolean verbose = FALSE;
198 if (global.fps_slowdown_factor > 1 &&
199 (FrameCounter % global.fps_slowdown_factor) &&
200 (just_scrolling || skip_even_when_not_scrolling))
202 redraw_mask &= ~REDRAW_MAIN;
204 last_frame_skipped = TRUE;
207 printf("FRAME SKIPPED\n");
211 if (last_frame_skipped)
212 redraw_mask |= REDRAW_FIELD;
214 last_frame_skipped = FALSE;
217 printf("frame not skipped\n");
221 /* synchronize X11 graphics at this point; if we would synchronize the
222 display immediately after the buffer switching (after the XFlush),
223 this could mean that we have to wait for the graphics to complete,
224 although we could go on doing calculations for the next frame */
228 if (redraw_mask & REDRAW_ALL)
230 BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
234 if (redraw_mask & REDRAW_FIELD)
236 if (game_status != GAME_MODE_PLAYING ||
237 redraw_mask & REDRAW_FROM_BACKBUFFER)
239 BlitBitmap(backbuffer, window,
240 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE, REAL_SX, REAL_SY);
244 int fx = FX, fy = FY;
246 if (setup.soft_scrolling)
248 fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
249 fy += (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
252 if (setup.soft_scrolling ||
253 ABS(ScreenMovPos) + ScrollStepSize == TILEX ||
254 ABS(ScreenMovPos) == ScrollStepSize ||
255 redraw_tiles > REDRAWTILES_THRESHOLD)
257 BlitBitmap(buffer, window, fx, fy, SXSIZE, SYSIZE, SX, SY);
261 printf("redrawing all (ScreenGfxPos == %d) because %s\n",
263 (setup.soft_scrolling ?
264 "setup.soft_scrolling" :
265 ABS(ScreenGfxPos) + ScrollStepSize == TILEX ?
266 "ABS(ScreenGfxPos) + ScrollStepSize == TILEX" :
267 ABS(ScreenGfxPos) == ScrollStepSize ?
268 "ABS(ScreenGfxPos) == ScrollStepSize" :
269 "redraw_tiles > REDRAWTILES_THRESHOLD"));
275 redraw_mask &= ~REDRAW_MAIN;
278 if (redraw_mask & REDRAW_DOORS)
280 if (redraw_mask & REDRAW_DOOR_1)
281 BlitBitmap(backbuffer, window, DX, DY, DXSIZE, DYSIZE, DX, DY);
283 if (redraw_mask & REDRAW_DOOR_2)
286 if ((redraw_mask & REDRAW_DOOR_2) == REDRAW_DOOR_2)
288 BlitBitmap(backbuffer, window, VX, VY, VXSIZE, VYSIZE, VX, VY);
292 if (redraw_mask & REDRAW_VIDEO_1)
293 BlitBitmap(backbuffer, window,
294 VX + VIDEO_DISPLAY1_XPOS, VY + VIDEO_DISPLAY1_YPOS,
295 VIDEO_DISPLAY_XSIZE, VIDEO_DISPLAY_YSIZE,
296 VX + VIDEO_DISPLAY1_XPOS, VY + VIDEO_DISPLAY1_YPOS);
297 if (redraw_mask & REDRAW_VIDEO_2)
298 BlitBitmap(backbuffer, window,
299 VX + VIDEO_DISPLAY2_XPOS, VY + VIDEO_DISPLAY2_YPOS,
300 VIDEO_DISPLAY_XSIZE, VIDEO_DISPLAY_YSIZE,
301 VX + VIDEO_DISPLAY2_XPOS, VY + VIDEO_DISPLAY2_YPOS);
302 if (redraw_mask & REDRAW_VIDEO_3)
303 BlitBitmap(backbuffer, window,
304 VX + VIDEO_CONTROL_XPOS, VY + VIDEO_CONTROL_YPOS,
305 VIDEO_CONTROL_XSIZE, VIDEO_CONTROL_YSIZE,
306 VX + VIDEO_CONTROL_XPOS, VY + VIDEO_CONTROL_YPOS);
311 if (redraw_mask & REDRAW_DOOR_3)
312 BlitBitmap(backbuffer, window, EX, EY, EXSIZE, EYSIZE, EX, EY);
314 redraw_mask &= ~REDRAW_DOORS;
317 if (redraw_mask & REDRAW_MICROLEVEL)
319 BlitBitmap(backbuffer, window, SX, SY + 10 * TILEY, SXSIZE, 7 * TILEY,
320 SX, SY + 10 * TILEY);
322 redraw_mask &= ~REDRAW_MICROLEVEL;
325 if (redraw_mask & REDRAW_TILES)
327 for (x = 0; x < SCR_FIELDX; x++)
328 for (y = 0 ; y < SCR_FIELDY; y++)
329 if (redraw[redraw_x1 + x][redraw_y1 + y])
330 BlitBitmap(buffer, window,
331 FX + x * TILEX, FY + y * TILEY, TILEX, TILEY,
332 SX + x * TILEX, SY + y * TILEY);
335 if (redraw_mask & REDRAW_FPS) /* display frames per second */
340 sprintf(info1, " (only every %d. frame)", global.fps_slowdown_factor);
341 if (!global.fps_slowdown)
344 sprintf(text, "%.1f fps%s", global.frames_per_second, info1);
345 DrawTextExt(window, SX, SY, text, FONT_TEXT_2, BLIT_OPAQUE);
350 for (x = 0; x < MAX_BUF_XSIZE; x++)
351 for (y = 0; y < MAX_BUF_YSIZE; y++)
354 redraw_mask = REDRAW_NONE;
360 long fading_delay = 300;
362 if (setup.fading && (redraw_mask & REDRAW_FIELD))
369 ClearRectangle(window, REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
372 for (i = 0; i < 2 * FULL_SYSIZE; i++)
374 for (y = 0; y < FULL_SYSIZE; y++)
376 BlitBitmap(backbuffer, window,
377 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
385 for (i = 1; i < FULL_SYSIZE; i+=2)
386 BlitBitmap(backbuffer, window,
387 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
393 SetClipOrigin(clip_gc[PIX_FADEMASK], 0, 0);
394 BlitBitmapMasked(backbuffer, window,
395 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
400 SetClipOrigin(clip_gc[PIX_FADEMASK], -1, -1);
401 BlitBitmapMasked(backbuffer, window,
402 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
407 SetClipOrigin(clip_gc[PIX_FADEMASK], 0, -1);
408 BlitBitmapMasked(backbuffer, window,
409 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
414 SetClipOrigin(clip_gc[PIX_FADEMASK], -1, 0);
415 BlitBitmapMasked(backbuffer, window,
416 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
421 redraw_mask &= ~REDRAW_MAIN;
428 void SetMainBackgroundImage(int graphic)
430 SetMainBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
431 graphic_info[graphic].bitmap ?
432 graphic_info[graphic].bitmap :
433 graphic_info[IMG_BACKGROUND].bitmap);
436 void SetDoorBackgroundImage(int graphic)
438 SetDoorBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
439 graphic_info[graphic].bitmap ?
440 graphic_info[graphic].bitmap :
441 graphic_info[IMG_BACKGROUND].bitmap);
444 void DrawBackground(int dst_x, int dst_y, int width, int height)
446 ClearRectangleOnBackground(backbuffer, dst_x, dst_y, width, height);
448 redraw_mask |= REDRAW_FIELD;
453 DrawBackground(REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
455 if (setup.soft_scrolling && game_status == GAME_MODE_PLAYING)
457 ClearRectangle(fieldbuffer, 0, 0, FXSIZE, FYSIZE);
458 SetDrawtoField(DRAW_BUFFERED);
461 SetDrawtoField(DRAW_BACKBUFFER);
463 if (setup.direct_draw && game_status == GAME_MODE_PLAYING)
465 ClearRectangle(window, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
466 SetDrawtoField(DRAW_DIRECT);
470 void MarkTileDirty(int x, int y)
472 int xx = redraw_x1 + x;
473 int yy = redraw_y1 + y;
478 redraw[xx][yy] = TRUE;
479 redraw_mask |= REDRAW_TILES;
482 void SetBorderElement()
486 BorderElement = EL_EMPTY;
488 for (y = 0; y < lev_fieldy && BorderElement == EL_EMPTY; y++)
490 for (x = 0; x < lev_fieldx; x++)
492 if (!IS_INDESTRUCTIBLE(Feld[x][y]))
493 BorderElement = EL_STEELWALL;
495 if (y != 0 && y != lev_fieldy - 1 && x != lev_fieldx - 1)
501 void SetRandomAnimationValue(int x, int y)
503 gfx.anim_random_frame = GfxRandom[x][y];
506 inline int getGraphicAnimationFrame(int graphic, int sync_frame)
508 /* animation synchronized with global frame counter, not move position */
509 if (graphic_info[graphic].anim_global_sync || sync_frame < 0)
510 sync_frame = FrameCounter;
512 return getAnimationFrame(graphic_info[graphic].anim_frames,
513 graphic_info[graphic].anim_delay,
514 graphic_info[graphic].anim_mode,
515 graphic_info[graphic].anim_start_frame,
519 inline void getGraphicSourceExt(int graphic, int frame, Bitmap **bitmap,
520 int *x, int *y, boolean get_backside)
522 struct GraphicInfo *g = &graphic_info[graphic];
523 int src_x = g->src_x + (get_backside ? g->offset2_x : 0);
524 int src_y = g->src_y + (get_backside ? g->offset2_y : 0);
528 if (g->offset_y == 0) /* frames are ordered horizontally */
530 int max_width = g->anim_frames_per_line * g->width;
532 int pos = (src_y / g->height) * max_width + src_x + frame * g->offset_x;
534 *x = pos % max_width;
535 *y = src_y % g->height + pos / max_width * g->height;
537 *x = (src_x + frame * g->offset_x) % max_width;
538 *y = src_y + (src_x + frame * g->offset_x) / max_width * g->height;
541 else if (g->offset_x == 0) /* frames are ordered vertically */
543 int max_height = g->anim_frames_per_line * g->height;
545 int pos = (src_x / g->width) * max_height + src_y + frame * g->offset_y;
547 *x = src_x % g->width + pos / max_height * g->width;
548 *y = pos % max_height;
550 *x = src_x + (src_y + frame * g->offset_y) / max_height * g->width;
551 *y = (src_y + frame * g->offset_y) % max_height;
554 else /* frames are ordered diagonally */
556 *x = src_x + frame * g->offset_x;
557 *y = src_y + frame * g->offset_y;
561 void getGraphicSource(int graphic, int frame, Bitmap **bitmap, int *x, int *y)
563 getGraphicSourceExt(graphic, frame, bitmap, x, y, FALSE);
566 void DrawGraphic(int x, int y, int graphic, int frame)
569 if (!IN_SCR_FIELD(x, y))
571 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
572 printf("DrawGraphic(): This should never happen!\n");
577 DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic, frame);
581 void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
587 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
588 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
591 void DrawGraphicThruMask(int x, int y, int graphic, int frame)
594 if (!IN_SCR_FIELD(x, y))
596 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
597 printf("DrawGraphicThruMask(): This should never happen!\n");
602 DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY, graphic,
607 void DrawGraphicThruMaskExt(DrawBuffer *d, int dst_x, int dst_y, int graphic,
613 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
615 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
616 dst_x - src_x, dst_y - src_y);
617 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dst_x, dst_y);
620 void DrawMiniGraphic(int x, int y, int graphic)
622 DrawMiniGraphicExt(drawto, SX + x * MINI_TILEX,SY + y * MINI_TILEY, graphic);
623 MarkTileDirty(x / 2, y / 2);
626 void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
628 struct GraphicInfo *g = &graphic_info[graphic];
630 int mini_starty = g->bitmap->height * 2 / 3;
633 *x = mini_startx + g->src_x / 2;
634 *y = mini_starty + g->src_y / 2;
637 void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
642 getMiniGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
643 BlitBitmap(src_bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
646 inline static void DrawGraphicShiftedNormal(int x, int y, int dx, int dy,
647 int graphic, int frame,
648 int cut_mode, int mask_mode)
653 int width = TILEX, height = TILEY;
656 if (dx || dy) /* shifted graphic */
658 if (x < BX1) /* object enters playfield from the left */
665 else if (x > BX2) /* object enters playfield from the right */
671 else if (x==BX1 && dx < 0) /* object leaves playfield to the left */
677 else if (x==BX2 && dx > 0) /* object leaves playfield to the right */
679 else if (dx) /* general horizontal movement */
680 MarkTileDirty(x + SIGN(dx), y);
682 if (y < BY1) /* object enters playfield from the top */
684 if (cut_mode==CUT_BELOW) /* object completely above top border */
692 else if (y > BY2) /* object enters playfield from the bottom */
698 else if (y==BY1 && dy < 0) /* object leaves playfield to the top */
704 else if (dy > 0 && cut_mode == CUT_ABOVE)
706 if (y == BY2) /* object completely above bottom border */
712 MarkTileDirty(x, y + 1);
713 } /* object leaves playfield to the bottom */
714 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
716 else if (dy) /* general vertical movement */
717 MarkTileDirty(x, y + SIGN(dy));
721 if (!IN_SCR_FIELD(x, y))
723 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
724 printf("DrawGraphicShifted(): This should never happen!\n");
729 if (width > 0 && height > 0)
731 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
736 dst_x = FX + x * TILEX + dx;
737 dst_y = FY + y * TILEY + dy;
739 if (mask_mode == USE_MASKING)
741 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
742 dst_x - src_x, dst_y - src_y);
743 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
747 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
754 inline static void DrawGraphicShiftedDouble(int x, int y, int dx, int dy,
755 int graphic, int frame,
756 int cut_mode, int mask_mode)
761 int width = TILEX, height = TILEY;
764 int x2 = x + SIGN(dx);
765 int y2 = y + SIGN(dy);
766 int anim_frames = graphic_info[graphic].anim_frames;
767 int sync_frame = (dx ? ABS(dx) : ABS(dy)) * anim_frames / TILESIZE;
769 /* re-calculate animation frame for two-tile movement animation */
770 frame = getGraphicAnimationFrame(graphic, sync_frame);
772 if (IN_SCR_FIELD(x1, y1)) /* movement start graphic inside screen area */
774 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, TRUE);
776 dst_x = FX + x1 * TILEX;
777 dst_y = FY + y1 * TILEY;
779 if (mask_mode == USE_MASKING)
781 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
782 dst_x - src_x, dst_y - src_y);
783 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
787 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
790 MarkTileDirty(x1, y1);
793 if (IN_SCR_FIELD(x2, y2)) /* movement end graphic inside screen area */
795 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, FALSE);
797 dst_x = FX + x2 * TILEX;
798 dst_y = FY + y2 * TILEY;
800 if (mask_mode == USE_MASKING)
802 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
803 dst_x - src_x, dst_y - src_y);
804 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
808 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
811 MarkTileDirty(x2, y2);
815 printf("::: DONE DrawGraphicShiftedDouble");
821 static void DrawGraphicShifted(int x, int y, int dx, int dy,
822 int graphic, int frame,
823 int cut_mode, int mask_mode)
827 DrawGraphic(x, y, graphic, frame);
832 if (graphic_info[graphic].double_movement) /* EM style movement images */
833 DrawGraphicShiftedDouble(x, y, dx, dy, graphic, frame, cut_mode,mask_mode);
835 DrawGraphicShiftedNormal(x, y, dx, dy, graphic, frame, cut_mode,mask_mode);
838 void DrawGraphicShiftedThruMask(int x, int y, int dx, int dy, int graphic,
839 int frame, int cut_mode)
841 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, USE_MASKING);
844 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
845 int cut_mode, int mask_mode)
847 int lx = LEVELX(x), ly = LEVELY(y);
851 if (IN_LEV_FIELD(lx, ly))
853 SetRandomAnimationValue(lx, ly);
855 graphic = el_act_dir2img(element, GfxAction[lx][ly], GfxDir[lx][ly]);
856 frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
858 /* do not use double (EM style) movement graphic when not moving */
859 if (graphic_info[graphic].double_movement && !dx && !dy)
861 graphic = el_act_dir2img(element, ACTION_DEFAULT, GfxDir[lx][ly]);
862 frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
865 else /* border element */
867 graphic = el2img(element);
868 frame = getGraphicAnimationFrame(graphic, -1);
871 if (element == EL_EXPANDABLE_WALL)
873 boolean left_stopped = FALSE, right_stopped = FALSE;
875 if (!IN_LEV_FIELD(lx - 1, ly) || IS_WALL(Feld[lx - 1][ly]))
877 if (!IN_LEV_FIELD(lx + 1, ly) || IS_WALL(Feld[lx + 1][ly]))
878 right_stopped = TRUE;
880 if (left_stopped && right_stopped)
882 else if (left_stopped)
884 graphic = IMG_EXPANDABLE_WALL_GROWING_RIGHT;
885 frame = graphic_info[graphic].anim_frames - 1;
887 else if (right_stopped)
889 graphic = IMG_EXPANDABLE_WALL_GROWING_LEFT;
890 frame = graphic_info[graphic].anim_frames - 1;
895 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
896 else if (mask_mode == USE_MASKING)
897 DrawGraphicThruMask(x, y, graphic, frame);
899 DrawGraphic(x, y, graphic, frame);
902 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
903 int cut_mode, int mask_mode)
905 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
906 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
907 cut_mode, mask_mode);
910 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
913 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
916 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
919 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
922 void DrawLevelElementThruMask(int x, int y, int element)
924 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
927 void DrawLevelFieldThruMask(int x, int y)
929 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
932 #define TILE_GFX_ELEMENT(x, y) \
933 (GfxElement[x][y] != EL_UNDEFINED && Feld[x][y] != EL_EXPLOSION ? \
934 GfxElement[x][y] : Feld[x][y])
936 static void DrawLevelFieldCrumbledSandExt(int x, int y, int graphic, int frame)
940 int sx = SCREENX(x), sy = SCREENY(y);
942 int width, height, cx, cy, i;
944 int crumbled_border_size = graphic_info[graphic].border_size;
946 int snip = TILEX / 8; /* number of border pixels from "crumbled graphic" */
948 static int xy[4][2] =
957 if (x == 0 && y == 7)
958 printf("::: %d, %d [%d]\n", GfxElement[x][y], Feld[x][y],
959 crumbled_border_size);
962 if (!IN_LEV_FIELD(x, y))
965 element = TILE_GFX_ELEMENT(x, y);
967 /* crumble field itself */
968 if (GFX_CRUMBLED(element) && !IS_MOVING(x, y))
970 if (!IN_SCR_FIELD(sx, sy))
973 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
975 for (i = 0; i < 4; i++)
977 int xx = x + xy[i][0];
978 int yy = y + xy[i][1];
981 element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
984 element = (IN_LEV_FIELD(xx, yy) ? Feld[xx][yy] : BorderElement);
987 /* check if neighbour field is of same type */
988 if (GFX_CRUMBLED(element) && !IS_MOVING(xx, yy))
992 if (Feld[x][y] == EL_CUSTOM_START + 123)
993 printf("::: crumble [%d] THE CHAOS ENGINE (%d, %d): %d, %d\n",
994 i, Feld[x][y], element,
995 GFX_CRUMBLED(element), IS_MOVING(x, y));
998 if (i == 1 || i == 2)
1000 width = crumbled_border_size;
1002 cx = (i == 2 ? TILEX - crumbled_border_size : 0);
1008 height = crumbled_border_size;
1010 cy = (i == 3 ? TILEY - crumbled_border_size : 0);
1013 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1014 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
1017 MarkTileDirty(sx, sy);
1019 else /* crumble neighbour fields */
1022 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1025 for (i = 0; i < 4; i++)
1027 int xx = x + xy[i][0];
1028 int yy = y + xy[i][1];
1029 int sxx = sx + xy[i][0];
1030 int syy = sy + xy[i][1];
1033 if (!IN_LEV_FIELD(xx, yy) ||
1034 !IN_SCR_FIELD(sxx, syy) ||
1038 element = TILE_GFX_ELEMENT(xx, yy);
1040 if (!GFX_CRUMBLED(element))
1043 if (!IN_LEV_FIELD(xx, yy) ||
1044 !IN_SCR_FIELD(sxx, syy) ||
1045 !GFX_CRUMBLED(Feld[xx][yy]) ||
1051 graphic = el_act2crm(Feld[xx][yy], ACTION_DEFAULT);
1052 crumbled_border_size = graphic_info[graphic].border_size;
1054 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1057 if (i == 1 || i == 2)
1059 width = crumbled_border_size;
1061 cx = (i == 1 ? TILEX - crumbled_border_size : 0);
1067 height = crumbled_border_size;
1069 cy = (i == 0 ? TILEY - crumbled_border_size : 0);
1072 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1073 width, height, FX + sxx * TILEX + cx, FY + syy * TILEY + cy);
1075 MarkTileDirty(sxx, syy);
1080 void DrawLevelFieldCrumbledSand(int x, int y)
1085 if (!IN_LEV_FIELD(x, y))
1088 graphic = el_act2crm(Feld[x][y], ACTION_DEFAULT);
1090 DrawLevelFieldCrumbledSandExt(x, y, graphic, 0);
1092 DrawLevelFieldCrumbledSandExt(x, y, IMG_SAND_CRUMBLED, 0);
1096 void DrawLevelFieldCrumbledSandDigging(int x, int y, int direction,
1100 int graphic1 = el_act_dir2img(GfxElement[x][y], ACTION_DIGGING, direction);
1101 int graphic2 = el_act_dir2crm(GfxElement[x][y], ACTION_DIGGING, direction);
1103 int graphic1 = el_act_dir2img(EL_SAND, ACTION_DIGGING, direction);
1104 int graphic2 = el_act_dir2img(EL_SAND_CRUMBLED, ACTION_DIGGING, direction);
1106 int frame1 = getGraphicAnimationFrame(graphic1, step_frame);
1107 int frame2 = getGraphicAnimationFrame(graphic2, step_frame);
1108 int sx = SCREENX(x), sy = SCREENY(y);
1110 DrawGraphic(sx, sy, graphic1, frame1);
1111 DrawLevelFieldCrumbledSandExt(x, y, graphic2, frame2);
1114 void DrawLevelFieldCrumbledSandNeighbours(int x, int y)
1116 int sx = SCREENX(x), sy = SCREENY(y);
1117 static int xy[4][2] =
1126 for (i = 0; i < 4; i++)
1128 int xx = x + xy[i][0];
1129 int yy = y + xy[i][1];
1130 int sxx = sx + xy[i][0];
1131 int syy = sy + xy[i][1];
1133 if (!IN_LEV_FIELD(xx, yy) ||
1134 !IN_SCR_FIELD(sxx, syy) ||
1135 !GFX_CRUMBLED(Feld[xx][yy]) ||
1139 DrawLevelField(xx, yy);
1143 static int getBorderElement(int x, int y)
1147 { EL_STEELWALL_TOPLEFT, EL_INVISIBLE_STEELWALL_TOPLEFT },
1148 { EL_STEELWALL_TOPRIGHT, EL_INVISIBLE_STEELWALL_TOPRIGHT },
1149 { EL_STEELWALL_BOTTOMLEFT, EL_INVISIBLE_STEELWALL_BOTTOMLEFT },
1150 { EL_STEELWALL_BOTTOMRIGHT, EL_INVISIBLE_STEELWALL_BOTTOMRIGHT },
1151 { EL_STEELWALL_VERTICAL, EL_INVISIBLE_STEELWALL_VERTICAL },
1152 { EL_STEELWALL_HORIZONTAL, EL_INVISIBLE_STEELWALL_HORIZONTAL },
1153 { EL_STEELWALL, EL_INVISIBLE_STEELWALL }
1155 int steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
1156 int steel_position = (x == -1 && y == -1 ? 0 :
1157 x == lev_fieldx && y == -1 ? 1 :
1158 x == -1 && y == lev_fieldy ? 2 :
1159 x == lev_fieldx && y == lev_fieldy ? 3 :
1160 x == -1 || x == lev_fieldx ? 4 :
1161 y == -1 || y == lev_fieldy ? 5 : 6);
1163 return border[steel_position][steel_type];
1166 void DrawScreenElement(int x, int y, int element)
1168 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1169 DrawLevelFieldCrumbledSand(LEVELX(x), LEVELY(y));
1172 void DrawLevelElement(int x, int y, int element)
1174 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1175 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1178 void DrawScreenField(int x, int y)
1180 int lx = LEVELX(x), ly = LEVELY(y);
1181 int element, content;
1183 if (!IN_LEV_FIELD(lx, ly))
1185 if (lx < -1 || lx > lev_fieldx || ly < -1 || ly > lev_fieldy)
1188 element = getBorderElement(lx, ly);
1190 DrawScreenElement(x, y, element);
1194 element = Feld[lx][ly];
1195 content = Store[lx][ly];
1197 if (IS_MOVING(lx, ly))
1199 int horiz_move = (MovDir[lx][ly] == MV_LEFT || MovDir[lx][ly] == MV_RIGHT);
1200 boolean cut_mode = NO_CUTTING;
1202 if (element == EL_QUICKSAND_EMPTYING ||
1203 element == EL_MAGIC_WALL_EMPTYING ||
1204 element == EL_BD_MAGIC_WALL_EMPTYING ||
1205 element == EL_AMOEBA_DROPPING)
1206 cut_mode = CUT_ABOVE;
1207 else if (element == EL_QUICKSAND_FILLING ||
1208 element == EL_MAGIC_WALL_FILLING ||
1209 element == EL_BD_MAGIC_WALL_FILLING)
1210 cut_mode = CUT_BELOW;
1212 if (cut_mode == CUT_ABOVE)
1213 DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1215 DrawScreenElement(x, y, EL_EMPTY);
1218 DrawScreenElementShifted(x, y, MovPos[lx][ly], 0, element, NO_CUTTING);
1219 else if (cut_mode == NO_CUTTING)
1220 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], element, cut_mode);
1222 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], content, cut_mode);
1224 if (content == EL_ACID)
1226 int dir = MovDir[lx][ly];
1227 int newlx = lx + (dir == MV_LEFT ? -1 : dir == MV_RIGHT ? +1 : 0);
1228 int newly = ly + (dir == MV_UP ? -1 : dir == MV_DOWN ? +1 : 0);
1230 DrawLevelElementThruMask(newlx, newly, EL_ACID);
1233 else if (IS_BLOCKED(lx, ly))
1238 boolean cut_mode = NO_CUTTING;
1239 int element_old, content_old;
1241 Blocked2Moving(lx, ly, &oldx, &oldy);
1244 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1245 MovDir[oldx][oldy] == MV_RIGHT);
1247 element_old = Feld[oldx][oldy];
1248 content_old = Store[oldx][oldy];
1250 if (element_old == EL_QUICKSAND_EMPTYING ||
1251 element_old == EL_MAGIC_WALL_EMPTYING ||
1252 element_old == EL_BD_MAGIC_WALL_EMPTYING ||
1253 element_old == EL_AMOEBA_DROPPING)
1254 cut_mode = CUT_ABOVE;
1256 DrawScreenElement(x, y, EL_EMPTY);
1259 DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
1261 else if (cut_mode == NO_CUTTING)
1262 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
1265 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
1268 else if (IS_DRAWABLE(element))
1269 DrawScreenElement(x, y, element);
1271 DrawScreenElement(x, y, EL_EMPTY);
1274 void DrawLevelField(int x, int y)
1276 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1277 DrawScreenField(SCREENX(x), SCREENY(y));
1278 else if (IS_MOVING(x, y))
1282 Moving2Blocked(x, y, &newx, &newy);
1283 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1284 DrawScreenField(SCREENX(newx), SCREENY(newy));
1286 else if (IS_BLOCKED(x, y))
1290 Blocked2Moving(x, y, &oldx, &oldy);
1291 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1292 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1296 void DrawMiniElement(int x, int y, int element)
1300 graphic = el2edimg(element);
1301 DrawMiniGraphic(x, y, graphic);
1304 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1306 int x = sx + scroll_x, y = sy + scroll_y;
1308 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1309 DrawMiniElement(sx, sy, EL_EMPTY);
1310 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1311 DrawMiniElement(sx, sy, Feld[x][y]);
1313 DrawMiniGraphic(sx, sy, el2edimg(getBorderElement(x, y)));
1316 void DrawEnvelopeBackground(int envelope_nr, int startx, int starty,
1317 int x, int y, int xsize, int ysize, int font_nr)
1319 int font_width = getFontWidth(font_nr);
1320 int font_height = getFontHeight(font_nr);
1321 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1324 int dst_x = SX + startx + x * font_width;
1325 int dst_y = SY + starty + y * font_height;
1326 int width = graphic_info[graphic].width;
1327 int height = graphic_info[graphic].height;
1328 int inner_width = MAX(width - 2 * font_width, font_width);
1329 int inner_height = MAX(height - 2 * font_height, font_height);
1330 int inner_sx = (width >= 3 * font_width ? font_width : 0);
1331 int inner_sy = (height >= 3 * font_height ? font_height : 0);
1332 boolean draw_masked = graphic_info[graphic].draw_masked;
1334 getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
1336 if (src_bitmap == NULL || width < font_width || height < font_height)
1338 ClearRectangle(drawto, dst_x, dst_y, font_width, font_height);
1342 src_x += (x == 0 ? 0 : x == xsize - 1 ? width - font_width :
1343 inner_sx + (x - 1) * font_width % inner_width);
1344 src_y += (y == 0 ? 0 : y == ysize - 1 ? height - font_height :
1345 inner_sy + (y - 1) * font_height % inner_height);
1349 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1350 dst_x - src_x, dst_y - src_y);
1351 BlitBitmapMasked(src_bitmap, drawto, src_x, src_y, font_width, font_height,
1355 BlitBitmap(src_bitmap, drawto, src_x, src_y, font_width, font_height,
1359 void AnimateEnvelope(int envelope_nr, int anim_mode, int action)
1361 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1363 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
1364 int mask_mode = (src_bitmap != NULL ? BLIT_MASKED : BLIT_ON_BACKGROUND);
1366 boolean draw_masked = graphic_info[graphic].draw_masked;
1367 int mask_mode = (draw_masked ? BLIT_MASKED : BLIT_ON_BACKGROUND);
1369 boolean ffwd_delay = (tape.playing && tape.fast_forward);
1370 boolean no_delay = (tape.warp_forward);
1371 unsigned long anim_delay = 0;
1372 int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
1373 int anim_delay_value = (no_delay ? 0 : frame_delay_value);
1374 int font_nr = FONT_ENVELOPE_1 + envelope_nr;
1375 int font_width = getFontWidth(font_nr);
1376 int font_height = getFontHeight(font_nr);
1377 int max_xsize = level.envelope_xsize[envelope_nr];
1378 int max_ysize = level.envelope_ysize[envelope_nr];
1379 int xstart = (anim_mode & ANIM_VERTICAL ? max_xsize : 0);
1380 int ystart = (anim_mode & ANIM_HORIZONTAL ? max_ysize : 0);
1381 int xend = max_xsize;
1382 int yend = (anim_mode != ANIM_DEFAULT ? max_ysize : 0);
1383 int xstep = (xstart < xend ? 1 : 0);
1384 int ystep = (ystart < yend || xstep == 0 ? 1 : 0);
1387 for (x = xstart, y = ystart; x <= xend && y <= yend; x += xstep, y += ystep)
1389 int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2;
1390 int ysize = (action == ACTION_CLOSING ? yend - (y - ystart) : y) + 2;
1391 int sx = (SXSIZE - xsize * font_width) / 2;
1392 int sy = (SYSIZE - ysize * font_height) / 2;
1395 SetDrawtoField(DRAW_BUFFERED);
1397 BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
1399 SetDrawtoField(DRAW_BACKBUFFER);
1401 for (yy = 0; yy < ysize; yy++) for (xx = 0; xx < xsize; xx++)
1402 DrawEnvelopeBackground(envelope_nr, sx,sy, xx,yy, xsize, ysize, font_nr);
1404 DrawTextToTextArea(SX + sx + font_width, SY + sy + font_height,
1405 level.envelope_text[envelope_nr], font_nr, max_xsize,
1406 xsize - 2, ysize - 2, mask_mode);
1408 redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
1411 WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
1415 void ShowEnvelope(int envelope_nr)
1417 int element = EL_ENVELOPE_1 + envelope_nr;
1418 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1419 int sound_opening = element_info[element].sound[ACTION_OPENING];
1420 int sound_closing = element_info[element].sound[ACTION_CLOSING];
1421 boolean ffwd_delay = (tape.playing && tape.fast_forward);
1422 boolean no_delay = (tape.warp_forward);
1423 int normal_delay_value = ONE_SECOND_DELAY / (ffwd_delay ? 2 : 1);
1424 int wait_delay_value = (no_delay ? 0 : normal_delay_value);
1425 int anim_mode = graphic_info[graphic].anim_mode;
1426 int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL:
1427 anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode);
1429 game.envelope_active = TRUE; /* needed for RedrawPlayfield() events */
1431 PlaySoundStereo(sound_opening, SOUND_MIDDLE);
1433 if (anim_mode == ANIM_DEFAULT)
1434 AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_OPENING);
1436 AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_OPENING);
1439 Delay(wait_delay_value);
1441 WaitForEventToContinue();
1443 PlaySoundStereo(sound_closing, SOUND_MIDDLE);
1445 if (anim_mode != ANIM_NONE)
1446 AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_CLOSING);
1448 if (anim_mode == ANIM_DEFAULT)
1449 AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_CLOSING);
1451 game.envelope_active = FALSE;
1453 SetDrawtoField(DRAW_BUFFERED);
1455 redraw_mask |= REDRAW_FIELD;
1459 void getMicroGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1461 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
1462 int mini_startx = src_bitmap->width * 3 / 4;
1463 int mini_starty = src_bitmap->height * 2 / 3;
1464 int src_x = mini_startx + graphic_info[graphic].src_x / 8;
1465 int src_y = mini_starty + graphic_info[graphic].src_y / 8;
1467 *bitmap = src_bitmap;
1472 void DrawMicroElement(int xpos, int ypos, int element)
1476 int graphic = el2preimg(element);
1478 getMicroGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1479 BlitBitmap(src_bitmap, drawto, src_x, src_y, MICRO_TILEX, MICRO_TILEY,
1487 SetDrawBackgroundMask(REDRAW_NONE);
1490 for (x = BX1; x <= BX2; x++)
1491 for (y = BY1; y <= BY2; y++)
1492 DrawScreenField(x, y);
1494 redraw_mask |= REDRAW_FIELD;
1497 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1501 for (x = 0; x < size_x; x++)
1502 for (y = 0; y < size_y; y++)
1503 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1505 redraw_mask |= REDRAW_FIELD;
1508 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1512 DrawBackground(xpos, ypos, MICROLEVEL_XSIZE, MICROLEVEL_YSIZE);
1514 if (lev_fieldx < STD_LEV_FIELDX)
1515 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1516 if (lev_fieldy < STD_LEV_FIELDY)
1517 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1519 xpos += MICRO_TILEX;
1520 ypos += MICRO_TILEY;
1522 for (x = -1; x <= STD_LEV_FIELDX; x++)
1524 for (y = -1; y <= STD_LEV_FIELDY; y++)
1526 int lx = from_x + x, ly = from_y + y;
1528 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1529 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1530 level.field[lx][ly]);
1531 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1
1532 && BorderElement != EL_EMPTY)
1533 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1534 getBorderElement(lx, ly));
1538 redraw_mask |= REDRAW_MICROLEVEL;
1541 #define MICROLABEL_EMPTY 0
1542 #define MICROLABEL_LEVEL_NAME 1
1543 #define MICROLABEL_LEVEL_AUTHOR_HEAD 2
1544 #define MICROLABEL_LEVEL_AUTHOR 3
1545 #define MICROLABEL_IMPORTED_FROM_HEAD 4
1546 #define MICROLABEL_IMPORTED_FROM 5
1547 #define MICROLABEL_IMPORTED_BY_HEAD 6
1548 #define MICROLABEL_IMPORTED_BY 7
1550 static void DrawMicroLevelLabelExt(int mode)
1552 char label_text[MAX_OUTPUT_LINESIZE + 1];
1553 int max_len_label_text;
1554 int font_nr = FONT_TEXT_2;
1557 if (mode == MICROLABEL_LEVEL_AUTHOR_HEAD ||
1558 mode == MICROLABEL_IMPORTED_FROM_HEAD ||
1559 mode == MICROLABEL_IMPORTED_BY_HEAD)
1560 font_nr = FONT_TEXT_3;
1562 max_len_label_text = SXSIZE / getFontWidth(font_nr);
1566 for (i = 0; i < max_len_label_text; i++)
1567 label_text[i] = ' ';
1568 label_text[max_len_label_text] = '\0';
1570 if (strlen(label_text) > 0)
1572 int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
1573 int lypos = MICROLABEL2_YPOS;
1575 DrawText(lxpos, lypos, label_text, font_nr);
1580 DrawBackground(SX, MICROLABEL2_YPOS, SXSIZE, getFontHeight(font_nr));
1585 (mode == MICROLABEL_LEVEL_NAME ? level.name :
1586 mode == MICROLABEL_LEVEL_AUTHOR_HEAD ? "created by" :
1587 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
1588 mode == MICROLABEL_IMPORTED_FROM_HEAD ? "imported from" :
1589 mode == MICROLABEL_IMPORTED_FROM ? leveldir_current->imported_from :
1590 mode == MICROLABEL_IMPORTED_BY_HEAD ? "imported by" :
1591 mode == MICROLABEL_IMPORTED_BY ? leveldir_current->imported_by :""),
1592 max_len_label_text);
1593 label_text[max_len_label_text] = '\0';
1595 if (strlen(label_text) > 0)
1597 int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
1598 int lypos = MICROLABEL2_YPOS;
1600 DrawText(lxpos, lypos, label_text, font_nr);
1603 redraw_mask |= REDRAW_MICROLEVEL;
1606 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1608 static unsigned long scroll_delay = 0;
1609 static unsigned long label_delay = 0;
1610 static int from_x, from_y, scroll_direction;
1611 static int label_state, label_counter;
1612 int last_game_status = game_status; /* save current game status */
1614 /* force PREVIEW font on preview level */
1615 game_status = GAME_MODE_PSEUDO_PREVIEW;
1619 from_x = from_y = 0;
1620 scroll_direction = MV_RIGHT;
1624 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1625 DrawMicroLevelLabelExt(label_state);
1627 /* initialize delay counters */
1628 DelayReached(&scroll_delay, 0);
1629 DelayReached(&label_delay, 0);
1631 if (leveldir_current->name)
1633 char label_text[MAX_OUTPUT_LINESIZE + 1];
1634 int font_nr = FONT_TEXT_1;
1635 int max_len_label_text = SXSIZE / getFontWidth(font_nr);
1638 strncpy(label_text, leveldir_current->name, max_len_label_text);
1639 label_text[max_len_label_text] = '\0';
1641 lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
1642 lypos = SY + MICROLABEL1_YPOS;
1644 DrawText(lxpos, lypos, label_text, font_nr);
1647 game_status = last_game_status; /* restore current game status */
1652 /* scroll micro level, if needed */
1653 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1654 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1656 switch (scroll_direction)
1662 scroll_direction = MV_UP;
1666 if (from_x < lev_fieldx - STD_LEV_FIELDX)
1669 scroll_direction = MV_DOWN;
1676 scroll_direction = MV_RIGHT;
1680 if (from_y < lev_fieldy - STD_LEV_FIELDY)
1683 scroll_direction = MV_LEFT;
1690 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1693 /* !!! THIS ALL SUCKS -- SHOULD BE CLEANLY REWRITTEN !!! */
1694 /* redraw micro level label, if needed */
1695 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1696 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1697 strcmp(level.author, leveldir_current->name) != 0 &&
1698 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1700 int max_label_counter = 23;
1702 if (leveldir_current->imported_from != NULL &&
1703 strlen(leveldir_current->imported_from) > 0)
1704 max_label_counter += 14;
1705 if (leveldir_current->imported_by != NULL &&
1706 strlen(leveldir_current->imported_by) > 0)
1707 max_label_counter += 14;
1709 label_counter = (label_counter + 1) % max_label_counter;
1710 label_state = (label_counter >= 0 && label_counter <= 7 ?
1711 MICROLABEL_LEVEL_NAME :
1712 label_counter >= 9 && label_counter <= 12 ?
1713 MICROLABEL_LEVEL_AUTHOR_HEAD :
1714 label_counter >= 14 && label_counter <= 21 ?
1715 MICROLABEL_LEVEL_AUTHOR :
1716 label_counter >= 23 && label_counter <= 26 ?
1717 MICROLABEL_IMPORTED_FROM_HEAD :
1718 label_counter >= 28 && label_counter <= 35 ?
1719 MICROLABEL_IMPORTED_FROM :
1720 label_counter >= 37 && label_counter <= 40 ?
1721 MICROLABEL_IMPORTED_BY_HEAD :
1722 label_counter >= 42 && label_counter <= 49 ?
1723 MICROLABEL_IMPORTED_BY : MICROLABEL_EMPTY);
1725 if (leveldir_current->imported_from == NULL &&
1726 (label_state == MICROLABEL_IMPORTED_FROM_HEAD ||
1727 label_state == MICROLABEL_IMPORTED_FROM))
1728 label_state = (label_state == MICROLABEL_IMPORTED_FROM_HEAD ?
1729 MICROLABEL_IMPORTED_BY_HEAD : MICROLABEL_IMPORTED_BY);
1731 DrawMicroLevelLabelExt(label_state);
1734 game_status = last_game_status; /* restore current game status */
1737 inline void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
1738 int graphic, int sync_frame, int mask_mode)
1740 int frame = getGraphicAnimationFrame(graphic, sync_frame);
1742 if (mask_mode == USE_MASKING)
1743 DrawGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
1745 DrawGraphicExt(dst_bitmap, x, y, graphic, frame);
1748 inline void DrawGraphicAnimation(int x, int y, int graphic)
1750 int lx = LEVELX(x), ly = LEVELY(y);
1752 if (!IN_SCR_FIELD(x, y))
1755 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
1756 graphic, GfxFrame[lx][ly], NO_MASKING);
1757 MarkTileDirty(x, y);
1760 void DrawLevelGraphicAnimation(int x, int y, int graphic)
1762 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
1765 void DrawLevelElementAnimation(int x, int y, int element)
1768 int graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
1770 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
1772 DrawGraphicAnimation(SCREENX(x), SCREENY(y), el2img(element));
1776 inline void DrawLevelGraphicAnimationIfNeeded(int x, int y, int graphic)
1778 int sx = SCREENX(x), sy = SCREENY(y);
1780 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
1783 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
1786 DrawGraphicAnimation(sx, sy, graphic);
1788 if (GFX_CRUMBLED(Feld[x][y]))
1789 DrawLevelFieldCrumbledSand(x, y);
1792 void DrawLevelElementAnimationIfNeeded(int x, int y, int element)
1794 int sx = SCREENX(x), sy = SCREENY(y);
1797 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
1800 graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
1802 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
1805 DrawGraphicAnimation(sx, sy, graphic);
1807 if (GFX_CRUMBLED(element))
1808 DrawLevelFieldCrumbledSand(x, y);
1811 static int getPlayerGraphic(struct PlayerInfo *player, int move_dir)
1813 if (player->use_murphy_graphic)
1815 /* this works only because currently only one player can be "murphy" ... */
1816 static int last_horizontal_dir = MV_LEFT;
1817 int graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, move_dir);
1819 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
1820 last_horizontal_dir = move_dir;
1822 if (graphic == IMG_SP_MURPHY) /* undefined => use special graphic */
1824 int direction = (player->is_snapping ? move_dir : last_horizontal_dir);
1826 graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, direction);
1832 return el_act_dir2img(player->element_nr, player->GfxAction, move_dir);
1835 static boolean equalGraphics(int graphic1, int graphic2)
1837 struct GraphicInfo *g1 = &graphic_info[graphic1];
1838 struct GraphicInfo *g2 = &graphic_info[graphic2];
1840 return (g1->bitmap == g2->bitmap &&
1841 g1->src_x == g2->src_x &&
1842 g1->src_y == g2->src_y &&
1843 g1->anim_frames == g2->anim_frames &&
1844 g1->anim_delay == g2->anim_delay &&
1845 g1->anim_mode == g2->anim_mode);
1848 void DrawAllPlayers()
1852 for (i = 0; i < MAX_PLAYERS; i++)
1853 if (stored_player[i].active)
1854 DrawPlayer(&stored_player[i]);
1857 void DrawPlayerField(int x, int y)
1859 if (!IS_PLAYER(x, y))
1862 DrawPlayer(PLAYERINFO(x, y));
1865 void DrawPlayer(struct PlayerInfo *player)
1867 int jx = player->jx;
1868 int jy = player->jy;
1869 int move_dir = player->MovDir;
1871 int last_jx = player->last_jx;
1872 int last_jy = player->last_jy;
1873 int next_jx = jx + (jx - last_jx);
1874 int next_jy = jy + (jy - last_jy);
1875 boolean player_is_moving = (last_jx != jx || last_jy != jy ? TRUE : FALSE);
1877 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? +1 : 0);
1878 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? +1 : 0);
1879 int last_jx = (player->is_moving ? jx - dx : jx);
1880 int last_jy = (player->is_moving ? jy - dy : jy);
1881 int next_jx = jx + dx;
1882 int next_jy = jy + dy;
1883 boolean player_is_moving = (player->MovPos ? TRUE : FALSE);
1885 int sx = SCREENX(jx), sy = SCREENY(jy);
1886 int sxx = 0, syy = 0;
1887 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
1889 int action = ACTION_DEFAULT;
1890 int last_player_graphic = getPlayerGraphic(player, move_dir);
1891 int last_player_frame = player->Frame;
1894 if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
1898 if (!IN_LEV_FIELD(jx, jy))
1900 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
1901 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
1902 printf("DrawPlayerField(): This should never happen!\n");
1907 if (element == EL_EXPLOSION)
1910 action = (player->is_pushing ? ACTION_PUSHING :
1911 player->is_digging ? ACTION_DIGGING :
1912 player->is_collecting ? ACTION_COLLECTING :
1913 player->is_moving ? ACTION_MOVING :
1914 player->is_snapping ? ACTION_SNAPPING :
1915 player->is_dropping ? ACTION_DROPPING :
1916 player->is_waiting ? player->action_waiting : ACTION_DEFAULT);
1918 InitPlayerGfxAnimation(player, action, move_dir);
1920 /* ----------------------------------------------------------------------- */
1921 /* draw things in the field the player is leaving, if needed */
1922 /* ----------------------------------------------------------------------- */
1925 if (player->is_moving)
1927 if (player_is_moving)
1930 if (Back[last_jx][last_jy] && IS_DRAWABLE(last_element))
1932 DrawLevelElement(last_jx, last_jy, Back[last_jx][last_jy]);
1934 if (last_element == EL_DYNAMITE_ACTIVE ||
1935 last_element == EL_SP_DISK_RED_ACTIVE)
1936 DrawDynamite(last_jx, last_jy);
1938 DrawLevelFieldThruMask(last_jx, last_jy);
1940 else if (last_element == EL_DYNAMITE_ACTIVE ||
1941 last_element == EL_SP_DISK_RED_ACTIVE)
1942 DrawDynamite(last_jx, last_jy);
1944 DrawLevelField(last_jx, last_jy);
1946 if (player->is_pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
1947 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
1950 if (!IN_SCR_FIELD(sx, sy))
1953 if (setup.direct_draw)
1954 SetDrawtoField(DRAW_BUFFERED);
1956 /* ----------------------------------------------------------------------- */
1957 /* draw things behind the player, if needed */
1958 /* ----------------------------------------------------------------------- */
1961 DrawLevelElement(jx, jy, Back[jx][jy]);
1962 else if (IS_ACTIVE_BOMB(element))
1963 DrawLevelElement(jx, jy, EL_EMPTY);
1966 if (player_is_moving && GfxElement[jx][jy] != EL_UNDEFINED)
1968 if (GFX_CRUMBLED(GfxElement[jx][jy]))
1969 DrawLevelFieldCrumbledSandDigging(jx, jy, move_dir, player->StepFrame);
1972 int old_element = GfxElement[jx][jy];
1973 int old_graphic = el_act_dir2img(old_element, action, move_dir);
1974 int frame = getGraphicAnimationFrame(old_graphic, player->StepFrame);
1976 DrawGraphic(sx, sy, old_graphic, frame);
1981 GfxElement[jx][jy] = EL_UNDEFINED;
1983 DrawLevelField(jx, jy);
1987 /* ----------------------------------------------------------------------- */
1988 /* draw player himself */
1989 /* ----------------------------------------------------------------------- */
1993 graphic = getPlayerGraphic(player, move_dir);
1995 /* in the case of changed player action or direction, prevent the current
1996 animation frame from being restarted for identical animations */
1997 if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic))
1998 player->Frame = last_player_frame;
2002 if (player->use_murphy_graphic)
2004 static int last_horizontal_dir = MV_LEFT;
2006 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
2007 last_horizontal_dir = move_dir;
2009 graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, move_dir);
2011 if (graphic == IMG_SP_MURPHY) /* undefined => use special graphic */
2013 int direction = (player->is_snapping ? move_dir : last_horizontal_dir);
2015 graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, direction);
2019 graphic = el_act_dir2img(player->element_nr, player->GfxAction, move_dir);
2023 frame = getGraphicAnimationFrame(graphic, player->Frame);
2027 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
2028 sxx = player->GfxPos;
2030 syy = player->GfxPos;
2033 if (!setup.soft_scrolling && ScreenMovPos)
2036 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
2038 if (SHIELD_ON(player))
2040 int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
2041 IMG_SHIELD_NORMAL_ACTIVE);
2042 int frame = getGraphicAnimationFrame(graphic, -1);
2044 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
2047 /* ----------------------------------------------------------------------- */
2048 /* draw things the player is pushing, if needed */
2049 /* ----------------------------------------------------------------------- */
2052 printf("::: %d, %d [%d, %d] [%d]\n",
2053 player->is_pushing, player_is_moving, player->GfxAction,
2054 player->is_moving, player_is_moving);
2058 if (player->is_pushing && player->is_moving)
2060 if (player->is_pushing && player_is_moving)
2064 int px = SCREENX(jx), py = SCREENY(jy);
2065 int pxx = (TILEX - ABS(sxx)) * dx;
2066 int pyy = (TILEY - ABS(syy)) * dy;
2068 int px = SCREENX(next_jx), py = SCREENY(next_jy);
2077 if (!IS_MOVING(jx, jy)) /* push movement already finished */
2078 element = Feld[next_jx][next_jy];
2080 graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
2081 frame = getGraphicAnimationFrame(graphic, player->StepFrame);
2083 /* draw background element under pushed element (like the Sokoban field) */
2084 if (Back[next_jx][next_jy])
2085 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
2087 /* masked drawing is needed for EMC style (double) movement graphics */
2088 DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame, NO_CUTTING);
2091 if (Back[next_jx][next_jy])
2092 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
2094 if ((pxx || pyy) && element == EL_SOKOBAN_OBJECT)
2095 DrawGraphicShiftedThruMask(px, py, pxx, pyy, IMG_SOKOBAN_OBJECT, 0,
2099 int element = MovingOrBlocked2Element(next_jx, next_jy);
2100 int graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
2102 int frame = getGraphicAnimationFrame(graphic, player->StepFrame);
2104 int frame = getGraphicAnimationFrame(graphic, player->Frame);
2108 /* masked drawing is needed for EMC style (double) movement graphics */
2109 DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame,
2112 DrawGraphicShifted(px, py, pxx, pyy, graphic, frame,
2113 NO_CUTTING, NO_MASKING);
2119 /* ----------------------------------------------------------------------- */
2120 /* draw things in front of player (active dynamite or dynabombs) */
2121 /* ----------------------------------------------------------------------- */
2123 if (IS_ACTIVE_BOMB(element))
2125 graphic = el2img(element);
2126 frame = getGraphicAnimationFrame(graphic, GfxFrame[jx][jy]);
2128 if (game.emulation == EMU_SUPAPLEX)
2129 DrawGraphic(sx, sy, IMG_SP_DISK_RED, frame);
2131 DrawGraphicThruMask(sx, sy, graphic, frame);
2134 if (player_is_moving && last_element == EL_EXPLOSION)
2136 int graphic = el_act2img(GfxElement[last_jx][last_jy], ACTION_EXPLODING);
2137 int delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2);
2138 int phase = ExplodePhase[last_jx][last_jy] - 1;
2139 int frame = getGraphicAnimationFrame(graphic, phase - delay);
2142 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy), graphic, frame);
2145 /* ----------------------------------------------------------------------- */
2146 /* draw elements the player is just walking/passing through/under */
2147 /* ----------------------------------------------------------------------- */
2149 if (player_is_moving)
2151 /* handle the field the player is leaving ... */
2152 if (IS_ACCESSIBLE_INSIDE(last_element))
2153 DrawLevelField(last_jx, last_jy);
2154 else if (IS_ACCESSIBLE_UNDER(last_element))
2155 DrawLevelFieldThruMask(last_jx, last_jy);
2159 /* do not redraw accessible elements if the player is just pushing them */
2160 if (!player_is_moving || !player->is_pushing)
2162 /* ... and the field the player is entering */
2163 if (IS_ACCESSIBLE_INSIDE(element))
2164 DrawLevelField(jx, jy);
2165 else if (IS_ACCESSIBLE_UNDER(element))
2166 DrawLevelFieldThruMask(jx, jy);
2172 /* !!! I have forgotton what this should be good for !!! */
2173 /* !!! causes player being visible when pushing from within tubes !!! */
2174 if (!player->is_pushing)
2177 /* ... and the field the player is entering */
2178 if (IS_ACCESSIBLE_INSIDE(element))
2179 DrawLevelField(jx, jy);
2180 else if (IS_ACCESSIBLE_UNDER(element))
2181 DrawLevelFieldThruMask(jx, jy);
2185 if (setup.direct_draw)
2187 int dst_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
2188 int dst_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
2189 int x_size = TILEX * (1 + ABS(jx - last_jx));
2190 int y_size = TILEY * (1 + ABS(jy - last_jy));
2192 BlitBitmap(drawto_field, window,
2193 dst_x, dst_y, x_size, y_size, dst_x, dst_y);
2194 SetDrawtoField(DRAW_DIRECT);
2197 MarkTileDirty(sx, sy);
2200 /* ------------------------------------------------------------------------- */
2202 void WaitForEventToContinue()
2204 boolean still_wait = TRUE;
2206 /* simulate releasing mouse button over last gadget, if still pressed */
2208 HandleGadgets(-1, -1, 0);
2210 button_status = MB_RELEASED;
2222 case EVENT_BUTTONPRESS:
2223 case EVENT_KEYPRESS:
2227 case EVENT_KEYRELEASE:
2228 ClearPlayerAction();
2232 HandleOtherEvents(&event);
2236 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2243 /* don't eat all CPU time */
2248 #define MAX_REQUEST_LINES 13
2249 #define MAX_REQUEST_LINE_FONT1_LEN 7
2250 #define MAX_REQUEST_LINE_FONT2_LEN 10
2252 boolean Request(char *text, unsigned int req_state)
2254 int mx, my, ty, result = -1;
2255 unsigned int old_door_state;
2256 int last_game_status = game_status; /* save current game status */
2257 int max_request_line_len = MAX_REQUEST_LINE_FONT1_LEN;
2258 int font_nr = FONT_TEXT_2;
2259 int max_word_len = 0;
2262 for (text_ptr = text; *text_ptr; text_ptr++)
2264 max_word_len = (*text_ptr != ' ' ? max_word_len + 1 : 0);
2266 if (max_word_len > MAX_REQUEST_LINE_FONT1_LEN)
2268 max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
2269 font_nr = FONT_LEVEL_NUMBER;
2276 if (game_status == GAME_MODE_PLAYING &&
2277 level.game_engine_type == GAME_ENGINE_TYPE_EM)
2278 BlitScreenToBitmap_EM(backbuffer);
2282 /* disable deactivated drawing when quick-loading level tape recording */
2283 if (tape.playing && tape.deactivate_display)
2284 TapeDeactivateDisplayOff(TRUE);
2288 SetMouseCursor(CURSOR_DEFAULT);
2291 #if defined(NETWORK_AVALIABLE)
2292 /* pause network game while waiting for request to answer */
2293 if (options.network &&
2294 game_status == GAME_MODE_PLAYING &&
2295 req_state & REQUEST_WAIT_FOR_INPUT)
2296 SendToServer_PausePlaying();
2299 old_door_state = GetDoorState();
2301 /* simulate releasing mouse button over last gadget, if still pressed */
2303 HandleGadgets(-1, -1, 0);
2307 if (old_door_state & DOOR_OPEN_1)
2309 CloseDoor(DOOR_CLOSE_1);
2311 /* save old door content */
2312 BlitBitmap(bitmap_db_door, bitmap_db_door,
2313 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
2314 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
2317 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
2319 /* clear door drawing field */
2320 DrawBackground(DX, DY, DXSIZE, DYSIZE);
2322 /* force DOOR font on preview level */
2323 game_status = GAME_MODE_PSEUDO_DOOR;
2325 /* write text for request */
2326 for (ty = 0; ty < MAX_REQUEST_LINES; ty++)
2328 char text_line[max_request_line_len + 1];
2334 for (tl = 0, tx = 0; tx < max_request_line_len; tl++, tx++)
2337 if (!tc || tc == ' ')
2348 strncpy(text_line, text, tl);
2351 DrawText(DX + (DXSIZE - tl * getFontWidth(font_nr)) / 2,
2352 DY + 8 + ty * (getFontHeight(font_nr) + 2),
2353 text_line, font_nr);
2355 text += tl + (tc == ' ' ? 1 : 0);
2358 game_status = last_game_status; /* restore current game status */
2360 if (req_state & REQ_ASK)
2362 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
2363 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
2365 else if (req_state & REQ_CONFIRM)
2367 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
2369 else if (req_state & REQ_PLAYER)
2371 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
2372 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
2373 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
2374 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
2377 /* copy request gadgets to door backbuffer */
2378 BlitBitmap(drawto, bitmap_db_door,
2379 DX, DY, DXSIZE, DYSIZE,
2380 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2382 OpenDoor(DOOR_OPEN_1);
2388 if (!(req_state & REQUEST_WAIT_FOR_INPUT))
2390 SetDrawBackgroundMask(REDRAW_FIELD);
2395 if (game_status != GAME_MODE_MAIN)
2398 button_status = MB_RELEASED;
2400 request_gadget_id = -1;
2402 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
2405 SetMouseCursor(CURSOR_DEFAULT);
2418 case EVENT_BUTTONPRESS:
2419 case EVENT_BUTTONRELEASE:
2420 case EVENT_MOTIONNOTIFY:
2422 if (event.type == EVENT_MOTIONNOTIFY)
2424 if (!PointerInWindow(window))
2425 continue; /* window and pointer are on different screens */
2430 motion_status = TRUE;
2431 mx = ((MotionEvent *) &event)->x;
2432 my = ((MotionEvent *) &event)->y;
2436 motion_status = FALSE;
2437 mx = ((ButtonEvent *) &event)->x;
2438 my = ((ButtonEvent *) &event)->y;
2439 if (event.type == EVENT_BUTTONPRESS)
2440 button_status = ((ButtonEvent *) &event)->button;
2442 button_status = MB_RELEASED;
2445 /* this sets 'request_gadget_id' */
2446 HandleGadgets(mx, my, button_status);
2448 switch(request_gadget_id)
2450 case TOOL_CTRL_ID_YES:
2453 case TOOL_CTRL_ID_NO:
2456 case TOOL_CTRL_ID_CONFIRM:
2457 result = TRUE | FALSE;
2460 case TOOL_CTRL_ID_PLAYER_1:
2463 case TOOL_CTRL_ID_PLAYER_2:
2466 case TOOL_CTRL_ID_PLAYER_3:
2469 case TOOL_CTRL_ID_PLAYER_4:
2480 case EVENT_KEYPRESS:
2481 switch(GetEventKey((KeyEvent *)&event, TRUE))
2494 if (req_state & REQ_PLAYER)
2498 case EVENT_KEYRELEASE:
2499 ClearPlayerAction();
2503 HandleOtherEvents(&event);
2507 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2509 int joy = AnyJoystick();
2511 if (joy & JOY_BUTTON_1)
2513 else if (joy & JOY_BUTTON_2)
2519 /* don't eat all CPU time */
2523 if (game_status != GAME_MODE_MAIN)
2528 if (!(req_state & REQ_STAY_OPEN))
2530 CloseDoor(DOOR_CLOSE_1);
2532 if (((old_door_state & DOOR_OPEN_1) && !(req_state & REQ_STAY_CLOSED)) ||
2533 (req_state & REQ_REOPEN))
2534 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
2539 SetDrawBackgroundMask(REDRAW_FIELD);
2541 #if defined(NETWORK_AVALIABLE)
2542 /* continue network game after request */
2543 if (options.network &&
2544 game_status == GAME_MODE_PLAYING &&
2545 req_state & REQUEST_WAIT_FOR_INPUT)
2546 SendToServer_ContinuePlaying();
2550 /* restore deactivated drawing when quick-loading level tape recording */
2551 if (tape.playing && tape.deactivate_display)
2552 TapeDeactivateDisplayOn();
2558 unsigned int OpenDoor(unsigned int door_state)
2560 if (door_state & DOOR_COPY_BACK)
2562 if (door_state & DOOR_OPEN_1)
2563 BlitBitmap(bitmap_db_door, bitmap_db_door,
2564 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
2565 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2567 if (door_state & DOOR_OPEN_2)
2568 BlitBitmap(bitmap_db_door, bitmap_db_door,
2569 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY2, VXSIZE, VYSIZE,
2570 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2572 door_state &= ~DOOR_COPY_BACK;
2575 return MoveDoor(door_state);
2578 unsigned int CloseDoor(unsigned int door_state)
2580 unsigned int old_door_state = GetDoorState();
2582 if (!(door_state & DOOR_NO_COPY_BACK))
2584 if (old_door_state & DOOR_OPEN_1)
2585 BlitBitmap(backbuffer, bitmap_db_door,
2586 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2588 if (old_door_state & DOOR_OPEN_2)
2589 BlitBitmap(backbuffer, bitmap_db_door,
2590 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2592 door_state &= ~DOOR_NO_COPY_BACK;
2595 return MoveDoor(door_state);
2598 unsigned int GetDoorState()
2600 return MoveDoor(DOOR_GET_STATE);
2603 unsigned int SetDoorState(unsigned int door_state)
2605 return MoveDoor(door_state | DOOR_SET_STATE);
2608 unsigned int MoveDoor(unsigned int door_state)
2610 static int door1 = DOOR_OPEN_1;
2611 static int door2 = DOOR_CLOSE_2;
2612 unsigned long door_delay = 0;
2613 unsigned long door_delay_value;
2616 if (door_state == DOOR_GET_STATE)
2617 return(door1 | door2);
2619 if (door_state & DOOR_SET_STATE)
2621 if (door_state & DOOR_ACTION_1)
2622 door1 = door_state & DOOR_ACTION_1;
2623 if (door_state & DOOR_ACTION_2)
2624 door2 = door_state & DOOR_ACTION_2;
2626 return(door1 | door2);
2629 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2630 door_state &= ~DOOR_OPEN_1;
2631 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2632 door_state &= ~DOOR_CLOSE_1;
2633 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2634 door_state &= ~DOOR_OPEN_2;
2635 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2636 door_state &= ~DOOR_CLOSE_2;
2638 door_delay_value = (door_state & DOOR_ACTION_1 ? door_1.step_delay :
2641 if (setup.quick_doors)
2643 stepsize = 20; /* must be choosen to always draw last frame */
2644 door_delay_value = 0;
2647 StopSound(SND_DOOR_OPENING);
2648 StopSound(SND_DOOR_CLOSING);
2652 if (global.autoplay_leveldir)
2654 door_state |= DOOR_NO_DELAY;
2655 door_state &= ~DOOR_CLOSE_ALL;
2658 if (door_state & DOOR_ACTION)
2660 boolean door_1_done = !(door_state & DOOR_ACTION_1);
2661 boolean door_2_done = !(door_state & DOOR_ACTION_2);
2662 int start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2663 int end = (door_state & DOOR_ACTION_1 &&
2664 door_1.anim_mode == ANIM_VERTICAL ? DYSIZE : DXSIZE);
2667 if (!(door_state & DOOR_NO_DELAY) && !setup.quick_doors)
2669 /* opening door sound has priority over simultaneously closing door */
2670 if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
2671 PlaySoundStereo(SND_DOOR_OPENING, SOUND_MIDDLE);
2672 else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
2673 PlaySoundStereo(SND_DOOR_CLOSING, SOUND_MIDDLE);
2676 for (x = start; x <= end && !(door_1_done && door_2_done); x += stepsize)
2678 Bitmap *bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2679 GC gc = bitmap->stored_clip_gc;
2681 if (door_state & DOOR_ACTION_1)
2683 int a = MIN(x * door_1.step_offset, end);
2684 int i = (door_state & DOOR_OPEN_1 ? end - a : a);
2688 BlitBitmap(bitmap_db_door, drawto,
2689 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i / 2,
2690 DXSIZE, DYSIZE - i / 2, DX, DY);
2692 ClearRectangle(drawto, DX, DY + DYSIZE - i / 2, DXSIZE, i / 2);
2695 if (door_1.anim_mode == ANIM_HORIZONTAL && x <= DXSIZE)
2697 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
2698 int dst1_x = DX + DXSIZE - i, dst1_y = DY;
2699 int src2_x = DXSIZE - i, src2_y = DOOR_GFX_PAGEY1;
2700 int dst2_x = DX, dst2_y = DY;
2701 int width = i, height = DYSIZE;
2703 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2704 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2707 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2708 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2711 else if (door_1.anim_mode == ANIM_VERTICAL && x <= DYSIZE)
2713 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
2714 int dst1_x = DX, dst1_y = DY + DYSIZE - i;
2715 int src2_x = 0, src2_y = DOOR_GFX_PAGEY1 + DYSIZE - i;
2716 int dst2_x = DX, dst2_y = DY;
2717 int width = DXSIZE, height = i;
2719 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2720 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2723 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2724 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2727 else if (x <= DXSIZE) /* ANIM_DEFAULT */
2729 int j = (door_1.anim_mode == ANIM_DEFAULT ? (DXSIZE - i) / 3 : 0);
2731 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2732 BlitBitmapMasked(bitmap, drawto,
2733 DXSIZE, DOOR_GFX_PAGEY1, i, 77,
2734 DX + DXSIZE - i, DY + j);
2735 BlitBitmapMasked(bitmap, drawto,
2736 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
2737 DX + DXSIZE - i, DY + 140 + j);
2738 SetClipOrigin(bitmap, gc, DX - DXSIZE + i,
2739 DY - (DOOR_GFX_PAGEY1 + j));
2740 BlitBitmapMasked(bitmap, drawto,
2741 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
2743 BlitBitmapMasked(bitmap, drawto,
2744 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
2747 BlitBitmapMasked(bitmap, drawto,
2748 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2750 BlitBitmapMasked(bitmap, drawto,
2751 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2753 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2754 BlitBitmapMasked(bitmap, drawto,
2755 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2756 DX + DXSIZE - i, DY + 77 + j);
2757 BlitBitmapMasked(bitmap, drawto,
2758 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2759 DX + DXSIZE - i, DY + 203 + j);
2762 redraw_mask |= REDRAW_DOOR_1;
2763 door_1_done = (a == end);
2766 if (door_state & DOOR_ACTION_2)
2768 int a = MIN(x * door_2.step_offset, VXSIZE);
2769 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - a : a);
2773 BlitBitmap(bitmap_db_door, drawto,
2774 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i / 2,
2775 VXSIZE, VYSIZE - i / 2, VX, VY);
2777 ClearRectangle(drawto, VX, VY + VYSIZE - i / 2, VXSIZE, i / 2);
2780 if (door_2.anim_mode == ANIM_HORIZONTAL && x <= VXSIZE)
2782 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
2783 int dst1_x = VX + VXSIZE - i, dst1_y = VY;
2784 int src2_x = VXSIZE - i, src2_y = DOOR_GFX_PAGEY2;
2785 int dst2_x = VX, dst2_y = VY;
2786 int width = i, height = VYSIZE;
2788 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2789 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2792 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2793 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2796 else if (door_2.anim_mode == ANIM_VERTICAL && x <= VYSIZE)
2798 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
2799 int dst1_x = VX, dst1_y = VY + VYSIZE - i;
2800 int src2_x = 0, src2_y = DOOR_GFX_PAGEY2 + VYSIZE - i;
2801 int dst2_x = VX, dst2_y = VY;
2802 int width = VXSIZE, height = i;
2804 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2805 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2808 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2809 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2812 else if (x <= VXSIZE) /* ANIM_DEFAULT */
2814 int j = (door_2.anim_mode == ANIM_DEFAULT ? (VXSIZE - i) / 3 : 0);
2816 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2817 BlitBitmapMasked(bitmap, drawto,
2818 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
2819 VX + VXSIZE - i, VY + j);
2820 SetClipOrigin(bitmap, gc,
2821 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2822 BlitBitmapMasked(bitmap, drawto,
2823 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
2826 BlitBitmapMasked(bitmap, drawto,
2827 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2828 i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
2829 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2830 BlitBitmapMasked(bitmap, drawto,
2831 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2833 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2836 redraw_mask |= REDRAW_DOOR_2;
2837 door_2_done = (a == VXSIZE);
2842 if (game_status == GAME_MODE_MAIN)
2845 if (!(door_state & DOOR_NO_DELAY))
2846 WaitUntilDelayReached(&door_delay, door_delay_value);
2851 if (setup.quick_doors)
2853 StopSound(SND_DOOR_OPENING);
2854 StopSound(SND_DOOR_CLOSING);
2858 if (door_state & DOOR_ACTION_1)
2859 door1 = door_state & DOOR_ACTION_1;
2860 if (door_state & DOOR_ACTION_2)
2861 door2 = door_state & DOOR_ACTION_2;
2863 return (door1 | door2);
2866 void DrawSpecialEditorDoor()
2868 /* draw bigger toolbox window */
2869 BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
2870 DOOR_GFX_PAGEX7, 0, EXSIZE + 8, 8,
2872 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2873 EX - 4, VY - 4, EXSIZE + 8, EYSIZE - VYSIZE + 4,
2876 redraw_mask |= REDRAW_ALL;
2879 void UndrawSpecialEditorDoor()
2881 /* draw normal tape recorder window */
2882 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2883 EX - 4, EY - 12, EXSIZE + 8, EYSIZE - VYSIZE + 12,
2886 redraw_mask |= REDRAW_ALL;
2890 /* ---------- new tool button stuff ---------------------------------------- */
2892 /* graphic position values for tool buttons */
2893 #define TOOL_BUTTON_YES_XPOS 2
2894 #define TOOL_BUTTON_YES_YPOS 250
2895 #define TOOL_BUTTON_YES_GFX_YPOS 0
2896 #define TOOL_BUTTON_YES_XSIZE 46
2897 #define TOOL_BUTTON_YES_YSIZE 28
2898 #define TOOL_BUTTON_NO_XPOS 52
2899 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2900 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2901 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2902 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2903 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2904 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2905 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2906 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2907 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2908 #define TOOL_BUTTON_PLAYER_XSIZE 30
2909 #define TOOL_BUTTON_PLAYER_YSIZE 30
2910 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2911 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2912 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2913 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2914 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2915 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2916 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2917 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2918 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2919 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2920 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2921 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2922 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2923 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2924 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2925 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2926 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2927 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2928 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2929 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2938 } toolbutton_info[NUM_TOOL_BUTTONS] =
2941 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2942 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2943 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2948 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2949 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2950 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2955 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2956 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2957 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2958 TOOL_CTRL_ID_CONFIRM,
2962 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2963 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2964 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2965 TOOL_CTRL_ID_PLAYER_1,
2969 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2970 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2971 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2972 TOOL_CTRL_ID_PLAYER_2,
2976 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2977 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2978 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2979 TOOL_CTRL_ID_PLAYER_3,
2983 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2984 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2985 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2986 TOOL_CTRL_ID_PLAYER_4,
2991 void CreateToolButtons()
2995 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2997 Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2998 Bitmap *deco_bitmap = None;
2999 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
3000 struct GadgetInfo *gi;
3001 unsigned long event_mask;
3002 int gd_xoffset, gd_yoffset;
3003 int gd_x1, gd_x2, gd_y;
3006 event_mask = GD_EVENT_RELEASED;
3008 gd_xoffset = toolbutton_info[i].xpos;
3009 gd_yoffset = toolbutton_info[i].ypos;
3010 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
3011 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
3012 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
3014 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
3016 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
3018 getMiniGraphicSource(PLAYER_NR_GFX(IMG_PLAYER_1, player_nr),
3019 &deco_bitmap, &deco_x, &deco_y);
3020 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
3021 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
3024 gi = CreateGadget(GDI_CUSTOM_ID, id,
3025 GDI_INFO_TEXT, toolbutton_info[i].infotext,
3026 GDI_X, DX + toolbutton_info[i].x,
3027 GDI_Y, DY + toolbutton_info[i].y,
3028 GDI_WIDTH, toolbutton_info[i].width,
3029 GDI_HEIGHT, toolbutton_info[i].height,
3030 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
3031 GDI_STATE, GD_BUTTON_UNPRESSED,
3032 GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
3033 GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
3034 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
3035 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
3036 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
3037 GDI_DECORATION_SHIFTING, 1, 1,
3038 GDI_EVENT_MASK, event_mask,
3039 GDI_CALLBACK_ACTION, HandleToolButtons,
3043 Error(ERR_EXIT, "cannot create gadget");
3045 tool_gadget[id] = gi;
3049 void FreeToolButtons()
3053 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
3054 FreeGadget(tool_gadget[i]);
3057 static void UnmapToolButtons()
3061 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
3062 UnmapGadget(tool_gadget[i]);
3065 static void HandleToolButtons(struct GadgetInfo *gi)
3067 request_gadget_id = gi->custom_id;
3072 static struct Mapping_EM_to_RND_object
3075 boolean is_rnd_to_em_mapping; /* unique mapping EM <-> RND */
3076 boolean is_backside; /* backside of moving element */
3082 em_object_mapping_list[] =
3085 Xblank, TRUE, FALSE,
3089 Yacid_splash_eB, FALSE, FALSE,
3090 EL_ACID_SPLASH_RIGHT, -1, -1
3093 Yacid_splash_wB, FALSE, FALSE,
3094 EL_ACID_SPLASH_LEFT, -1, -1
3097 #ifdef EM_ENGINE_BAD_ROLL
3099 Xstone_force_e, FALSE, FALSE,
3100 EL_ROCK, -1, MV_BIT_RIGHT
3103 Xstone_force_w, FALSE, FALSE,
3104 EL_ROCK, -1, MV_BIT_LEFT
3107 Xnut_force_e, FALSE, FALSE,
3108 EL_NUT, -1, MV_BIT_RIGHT
3111 Xnut_force_w, FALSE, FALSE,
3112 EL_NUT, -1, MV_BIT_LEFT
3115 Xspring_force_e, FALSE, FALSE,
3116 EL_SPRING, -1, MV_BIT_RIGHT
3119 Xspring_force_w, FALSE, FALSE,
3120 EL_SPRING, -1, MV_BIT_LEFT
3123 Xemerald_force_e, FALSE, FALSE,
3124 EL_EMERALD, -1, MV_BIT_RIGHT
3127 Xemerald_force_w, FALSE, FALSE,
3128 EL_EMERALD, -1, MV_BIT_LEFT
3131 Xdiamond_force_e, FALSE, FALSE,
3132 EL_DIAMOND, -1, MV_BIT_RIGHT
3135 Xdiamond_force_w, FALSE, FALSE,
3136 EL_DIAMOND, -1, MV_BIT_LEFT
3139 Xbomb_force_e, FALSE, FALSE,
3140 EL_BOMB, -1, MV_BIT_RIGHT
3143 Xbomb_force_w, FALSE, FALSE,
3144 EL_BOMB, -1, MV_BIT_LEFT
3146 #endif /* EM_ENGINE_BAD_ROLL */
3149 Xstone, TRUE, FALSE,
3153 Xstone_pause, FALSE, FALSE,
3157 Xstone_fall, FALSE, FALSE,
3161 Ystone_s, FALSE, FALSE,
3162 EL_ROCK, ACTION_FALLING, -1
3165 Ystone_sB, FALSE, TRUE,
3166 EL_ROCK, ACTION_FALLING, -1
3169 Ystone_e, FALSE, FALSE,
3170 EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT
3173 Ystone_eB, FALSE, TRUE,
3174 EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT
3177 Ystone_w, FALSE, FALSE,
3178 EL_ROCK, ACTION_MOVING, MV_BIT_LEFT
3181 Ystone_wB, FALSE, TRUE,
3182 EL_ROCK, ACTION_MOVING, MV_BIT_LEFT
3189 Xnut_pause, FALSE, FALSE,
3193 Xnut_fall, FALSE, FALSE,
3197 Ynut_s, FALSE, FALSE,
3198 EL_NUT, ACTION_FALLING, -1
3201 Ynut_sB, FALSE, TRUE,
3202 EL_NUT, ACTION_FALLING, -1
3205 Ynut_e, FALSE, FALSE,
3206 EL_NUT, ACTION_MOVING, MV_BIT_RIGHT
3209 Ynut_eB, FALSE, TRUE,
3210 EL_NUT, ACTION_MOVING, MV_BIT_RIGHT
3213 Ynut_w, FALSE, FALSE,
3214 EL_NUT, ACTION_MOVING, MV_BIT_LEFT
3217 Ynut_wB, FALSE, TRUE,
3218 EL_NUT, ACTION_MOVING, MV_BIT_LEFT
3221 Xbug_n, TRUE, FALSE,
3225 Xbug_e, TRUE, FALSE,
3226 EL_BUG_RIGHT, -1, -1
3229 Xbug_s, TRUE, FALSE,
3233 Xbug_w, TRUE, FALSE,
3237 Xbug_gon, FALSE, FALSE,
3241 Xbug_goe, FALSE, FALSE,
3242 EL_BUG_RIGHT, -1, -1
3245 Xbug_gos, FALSE, FALSE,
3249 Xbug_gow, FALSE, FALSE,
3253 Ybug_n, FALSE, FALSE,
3254 EL_BUG, ACTION_MOVING, MV_BIT_UP
3257 Ybug_nB, FALSE, TRUE,
3258 EL_BUG, ACTION_MOVING, MV_BIT_UP
3261 Ybug_e, FALSE, FALSE,
3262 EL_BUG, ACTION_MOVING, MV_BIT_RIGHT
3265 Ybug_eB, FALSE, TRUE,
3266 EL_BUG, ACTION_MOVING, MV_BIT_RIGHT
3269 Ybug_s, FALSE, FALSE,
3270 EL_BUG, ACTION_MOVING, MV_BIT_DOWN
3273 Ybug_sB, FALSE, TRUE,
3274 EL_BUG, ACTION_MOVING, MV_BIT_DOWN
3277 Ybug_w, FALSE, FALSE,
3278 EL_BUG, ACTION_MOVING, MV_BIT_LEFT
3281 Ybug_wB, FALSE, TRUE,
3282 EL_BUG, ACTION_MOVING, MV_BIT_LEFT
3285 Ybug_w_n, FALSE, FALSE,
3286 EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_UP
3289 Ybug_n_e, FALSE, FALSE,
3290 EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3293 Ybug_e_s, FALSE, FALSE,
3294 EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
3297 Ybug_s_w, FALSE, FALSE,
3298 EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3301 Ybug_e_n, FALSE, FALSE,
3302 EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
3305 Ybug_s_e, FALSE, FALSE,
3306 EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3309 Ybug_w_s, FALSE, FALSE,
3310 EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
3313 Ybug_n_w, FALSE, FALSE,
3314 EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3317 Ybug_stone, FALSE, FALSE,
3318 EL_BUG, ACTION_SMASHED_BY_ROCK, -1
3321 Ybug_spring, FALSE, FALSE,
3322 EL_BUG, ACTION_SMASHED_BY_SPRING, -1
3325 Xtank_n, TRUE, FALSE,
3326 EL_SPACESHIP_UP, -1, -1
3329 Xtank_e, TRUE, FALSE,
3330 EL_SPACESHIP_RIGHT, -1, -1
3333 Xtank_s, TRUE, FALSE,
3334 EL_SPACESHIP_DOWN, -1, -1
3337 Xtank_w, TRUE, FALSE,
3338 EL_SPACESHIP_LEFT, -1, -1
3341 Xtank_gon, FALSE, FALSE,
3342 EL_SPACESHIP_UP, -1, -1
3345 Xtank_goe, FALSE, FALSE,
3346 EL_SPACESHIP_RIGHT, -1, -1
3349 Xtank_gos, FALSE, FALSE,
3350 EL_SPACESHIP_DOWN, -1, -1
3353 Xtank_gow, FALSE, FALSE,
3354 EL_SPACESHIP_LEFT, -1, -1
3357 Ytank_n, FALSE, FALSE,
3358 EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP
3361 Ytank_nB, FALSE, TRUE,
3362 EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP
3365 Ytank_e, FALSE, FALSE,
3366 EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT
3369 Ytank_eB, FALSE, TRUE,
3370 EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT
3373 Ytank_s, FALSE, FALSE,
3374 EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN
3377 Ytank_sB, FALSE, TRUE,
3378 EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN
3381 Ytank_w, FALSE, FALSE,
3382 EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT
3385 Ytank_wB, FALSE, TRUE,
3386 EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT
3389 Ytank_w_n, FALSE, FALSE,
3390 EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_UP
3393 Ytank_n_e, FALSE, FALSE,
3394 EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3397 Ytank_e_s, FALSE, FALSE,
3398 EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
3401 Ytank_s_w, FALSE, FALSE,
3402 EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3405 Ytank_e_n, FALSE, FALSE,
3406 EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
3409 Ytank_s_e, FALSE, FALSE,
3410 EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3413 Ytank_w_s, FALSE, FALSE,
3414 EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
3417 Ytank_n_w, FALSE, FALSE,
3418 EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3421 Ytank_stone, FALSE, FALSE,
3422 EL_SPACESHIP, ACTION_SMASHED_BY_ROCK, -1
3425 Ytank_spring, FALSE, FALSE,
3426 EL_SPACESHIP, ACTION_SMASHED_BY_SPRING, -1
3429 Xandroid, TRUE, FALSE,
3430 EL_EMC_ANDROID, ACTION_ACTIVE, -1
3433 Xandroid_1_n, FALSE, FALSE,
3434 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_UP
3437 Xandroid_2_n, FALSE, FALSE,
3438 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_UP
3441 Xandroid_1_e, FALSE, FALSE,
3442 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_RIGHT
3445 Xandroid_2_e, FALSE, FALSE,
3446 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_RIGHT
3449 Xandroid_1_w, FALSE, FALSE,
3450 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_LEFT
3453 Xandroid_2_w, FALSE, FALSE,
3454 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_LEFT
3457 Xandroid_1_s, FALSE, FALSE,
3458 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_DOWN
3461 Xandroid_2_s, FALSE, FALSE,
3462 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_DOWN
3465 Yandroid_n, FALSE, FALSE,
3466 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_UP
3469 Yandroid_nB, FALSE, TRUE,
3470 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_UP
3473 Yandroid_ne, FALSE, FALSE,
3474 EL_EMC_ANDROID, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3477 Yandroid_neB, FALSE, TRUE,
3478 EL_EMC_ANDROID, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3481 Yandroid_e, FALSE, FALSE,
3482 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_RIGHT
3485 Yandroid_eB, FALSE, TRUE,
3486 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_RIGHT
3489 Yandroid_se, FALSE, FALSE,
3490 EL_EMC_ANDROID, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3493 Yandroid_seB, FALSE, TRUE,
3494 EL_EMC_ANDROID, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3497 Yandroid_s, FALSE, FALSE,
3498 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_DOWN
3501 Yandroid_sB, FALSE, TRUE,
3502 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_DOWN
3505 Yandroid_sw, FALSE, FALSE,
3506 EL_EMC_ANDROID, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3509 Yandroid_swB, FALSE, TRUE,
3510 EL_EMC_ANDROID, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3513 Yandroid_w, FALSE, FALSE,
3514 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_LEFT
3517 Yandroid_wB, FALSE, TRUE,
3518 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_LEFT
3521 Yandroid_nw, FALSE, FALSE,
3522 EL_EMC_ANDROID, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3525 Yandroid_nwB, FALSE, TRUE,
3526 EL_EMC_ANDROID, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3529 Xspring, TRUE, FALSE,
3533 Xspring_pause, FALSE, FALSE,
3537 Xspring_e, FALSE, FALSE,
3541 Xspring_w, FALSE, FALSE,
3545 Xspring_fall, FALSE, FALSE,
3549 Yspring_s, FALSE, FALSE,
3550 EL_SPRING, ACTION_FALLING, -1
3553 Yspring_sB, FALSE, TRUE,
3554 EL_SPRING, ACTION_FALLING, -1
3557 Yspring_e, FALSE, FALSE,
3558 EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT
3561 Yspring_eB, FALSE, TRUE,
3562 EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT
3565 Yspring_w, FALSE, FALSE,
3566 EL_SPRING, ACTION_MOVING, MV_BIT_LEFT
3569 Yspring_wB, FALSE, TRUE,
3570 EL_SPRING, ACTION_MOVING, MV_BIT_LEFT
3573 Yspring_kill_e, FALSE, FALSE,
3574 EL_ROBOT, ACTION_SLURPED_BY_SPRING, MV_BIT_RIGHT
3577 Yspring_kill_eB, FALSE, TRUE,
3578 EL_ROBOT, ACTION_SLURPED_BY_SPRING, MV_BIT_RIGHT
3581 Yspring_kill_w, FALSE, FALSE,
3582 EL_ROBOT, ACTION_SLURPED_BY_SPRING, MV_BIT_LEFT
3585 Yspring_kill_wB, FALSE, TRUE,
3586 EL_ROBOT, ACTION_SLURPED_BY_SPRING, MV_BIT_LEFT
3589 Xeater_n, TRUE, FALSE,
3593 Xeater_e, FALSE, FALSE,
3597 Xeater_w, FALSE, FALSE,
3601 Xeater_s, FALSE, FALSE,
3605 Yeater_n, FALSE, FALSE,
3606 EL_YAMYAM, ACTION_MOVING, MV_BIT_UP
3609 Yeater_nB, FALSE, TRUE,
3610 EL_YAMYAM, ACTION_MOVING, MV_BIT_UP
3613 Yeater_e, FALSE, FALSE,
3614 EL_YAMYAM, ACTION_MOVING, MV_BIT_RIGHT
3617 Yeater_eB, FALSE, TRUE,
3618 EL_YAMYAM, ACTION_MOVING, MV_BIT_RIGHT
3621 Yeater_s, FALSE, FALSE,
3622 EL_YAMYAM, ACTION_MOVING, MV_BIT_DOWN
3625 Yeater_sB, FALSE, TRUE,
3626 EL_YAMYAM, ACTION_MOVING, MV_BIT_DOWN
3629 Yeater_w, FALSE, FALSE,
3630 EL_YAMYAM, ACTION_MOVING, MV_BIT_LEFT
3633 Yeater_wB, FALSE, TRUE,
3634 EL_YAMYAM, ACTION_MOVING, MV_BIT_LEFT
3637 Yeater_stone, FALSE, FALSE,
3638 EL_YAMYAM, ACTION_SMASHED_BY_ROCK, -1
3641 Yeater_spring, FALSE, FALSE,
3642 EL_YAMYAM, ACTION_SMASHED_BY_SPRING, -1
3645 Xalien, TRUE, FALSE,
3649 Xalien_pause, FALSE, FALSE,
3653 Yalien_n, FALSE, FALSE,
3654 EL_ROBOT, ACTION_MOVING, MV_BIT_UP
3657 Yalien_nB, FALSE, TRUE,
3658 EL_ROBOT, ACTION_MOVING, MV_BIT_UP
3661 Yalien_e, FALSE, FALSE,
3662 EL_ROBOT, ACTION_MOVING, MV_BIT_RIGHT
3665 Yalien_eB, FALSE, TRUE,
3666 EL_ROBOT, ACTION_MOVING, MV_BIT_RIGHT
3669 Yalien_s, FALSE, FALSE,
3670 EL_ROBOT, ACTION_MOVING, MV_BIT_DOWN
3673 Yalien_sB, FALSE, TRUE,
3674 EL_ROBOT, ACTION_MOVING, MV_BIT_DOWN
3677 Yalien_w, FALSE, FALSE,
3678 EL_ROBOT, ACTION_MOVING, MV_BIT_LEFT
3681 Yalien_wB, FALSE, TRUE,
3682 EL_ROBOT, ACTION_MOVING, MV_BIT_LEFT
3685 Yalien_stone, FALSE, FALSE,
3686 EL_ROBOT, ACTION_SMASHED_BY_ROCK, -1
3689 Yalien_spring, FALSE, FALSE,
3690 EL_ROBOT, ACTION_SMASHED_BY_SPRING, -1
3693 Xemerald, TRUE, FALSE,
3697 Xemerald_pause, FALSE, FALSE,
3701 Xemerald_fall, FALSE, FALSE,
3705 Xemerald_shine, FALSE, FALSE,
3706 EL_EMERALD, ACTION_TWINKLING, -1
3709 Yemerald_s, FALSE, FALSE,
3710 EL_EMERALD, ACTION_FALLING, -1
3713 Yemerald_sB, FALSE, TRUE,
3714 EL_EMERALD, ACTION_FALLING, -1
3717 Yemerald_e, FALSE, FALSE,
3718 EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT
3721 Yemerald_eB, FALSE, TRUE,
3722 EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT
3725 Yemerald_w, FALSE, FALSE,
3726 EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT
3729 Yemerald_wB, FALSE, TRUE,
3730 EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT
3733 Yemerald_eat, FALSE, FALSE,
3734 EL_EMERALD, ACTION_COLLECTING, -1
3737 Yemerald_stone, FALSE, FALSE,
3738 EL_NUT, ACTION_BREAKING, -1
3741 Xdiamond, TRUE, FALSE,
3745 Xdiamond_pause, FALSE, FALSE,
3749 Xdiamond_fall, FALSE, FALSE,
3753 Xdiamond_shine, FALSE, FALSE,
3754 EL_DIAMOND, ACTION_TWINKLING, -1
3757 Ydiamond_s, FALSE, FALSE,
3758 EL_DIAMOND, ACTION_FALLING, -1
3761 Ydiamond_sB, FALSE, TRUE,
3762 EL_DIAMOND, ACTION_FALLING, -1
3765 Ydiamond_e, FALSE, FALSE,
3766 EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT
3769 Ydiamond_eB, FALSE, TRUE,
3770 EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT
3773 Ydiamond_w, FALSE, FALSE,
3774 EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT
3777 Ydiamond_wB, FALSE, TRUE,
3778 EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT
3781 Ydiamond_eat, FALSE, FALSE,
3782 EL_DIAMOND, ACTION_COLLECTING, -1
3785 Ydiamond_stone, FALSE, FALSE,
3786 EL_DIAMOND, ACTION_SMASHED_BY_ROCK, -1
3789 Xdrip_fall, TRUE, FALSE,
3790 EL_AMOEBA_DROP, -1, -1
3793 Xdrip_stretch, FALSE, FALSE,
3794 EL_AMOEBA_DROP, ACTION_FALLING, -1
3797 Xdrip_stretchB, FALSE, TRUE,
3798 EL_AMOEBA_DROP, ACTION_FALLING, -1
3801 Xdrip_eat, FALSE, FALSE,
3802 EL_AMOEBA_DROP, ACTION_GROWING, -1
3805 Ydrip_s1, FALSE, FALSE,
3806 EL_AMOEBA_DROP, ACTION_FALLING, -1
3809 Ydrip_s1B, FALSE, TRUE,
3810 EL_AMOEBA_DROP, ACTION_FALLING, -1
3813 Ydrip_s2, FALSE, FALSE,
3814 EL_AMOEBA_DROP, ACTION_FALLING, -1
3817 Ydrip_s2B, FALSE, TRUE,
3818 EL_AMOEBA_DROP, ACTION_FALLING, -1
3825 Xbomb_pause, FALSE, FALSE,
3829 Xbomb_fall, FALSE, FALSE,
3833 Ybomb_s, FALSE, FALSE,
3834 EL_BOMB, ACTION_FALLING, -1
3837 Ybomb_sB, FALSE, TRUE,
3838 EL_BOMB, ACTION_FALLING, -1
3841 Ybomb_e, FALSE, FALSE,
3842 EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT
3845 Ybomb_eB, FALSE, TRUE,
3846 EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT
3849 Ybomb_w, FALSE, FALSE,
3850 EL_BOMB, ACTION_MOVING, MV_BIT_LEFT
3853 Ybomb_wB, FALSE, TRUE,
3854 EL_BOMB, ACTION_MOVING, MV_BIT_LEFT
3857 Ybomb_eat, FALSE, FALSE,
3858 EL_BOMB, ACTION_ACTIVATING, -1
3861 Xballoon, TRUE, FALSE,
3865 Yballoon_n, FALSE, FALSE,
3866 EL_BALLOON, ACTION_MOVING, MV_BIT_UP
3869 Yballoon_nB, FALSE, TRUE,
3870 EL_BALLOON, ACTION_MOVING, MV_BIT_UP
3873 Yballoon_e, FALSE, FALSE,
3874 EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT
3877 Yballoon_eB, FALSE, TRUE,
3878 EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT
3881 Yballoon_s, FALSE, FALSE,
3882 EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN
3885 Yballoon_sB, FALSE, TRUE,
3886 EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN
3889 Yballoon_w, FALSE, FALSE,
3890 EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT
3893 Yballoon_wB, FALSE, TRUE,
3894 EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT
3897 Xgrass, TRUE, FALSE,
3898 EL_EMC_GRASS, -1, -1
3901 Ygrass_nB, FALSE, FALSE,
3902 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_UP
3905 Ygrass_eB, FALSE, FALSE,
3906 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_RIGHT
3909 Ygrass_sB, FALSE, FALSE,
3910 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_DOWN
3913 Ygrass_wB, FALSE, FALSE,
3914 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_LEFT
3921 Ydirt_nB, FALSE, FALSE,
3922 EL_SAND, ACTION_DIGGING, MV_BIT_UP
3925 Ydirt_eB, FALSE, FALSE,
3926 EL_SAND, ACTION_DIGGING, MV_BIT_RIGHT
3929 Ydirt_sB, FALSE, FALSE,
3930 EL_SAND, ACTION_DIGGING, MV_BIT_DOWN
3933 Ydirt_wB, FALSE, FALSE,
3934 EL_SAND, ACTION_DIGGING, MV_BIT_LEFT
3937 Xacid_ne, TRUE, FALSE,
3938 EL_ACID_POOL_TOPRIGHT, -1, -1
3941 Xacid_se, TRUE, FALSE,
3942 EL_ACID_POOL_BOTTOMRIGHT, -1, -1
3945 Xacid_s, TRUE, FALSE,
3946 EL_ACID_POOL_BOTTOM, -1, -1
3949 Xacid_sw, TRUE, FALSE,
3950 EL_ACID_POOL_BOTTOMLEFT, -1, -1
3953 Xacid_nw, TRUE, FALSE,
3954 EL_ACID_POOL_TOPLEFT, -1, -1
3957 Xacid_1, TRUE, FALSE,
3961 Xacid_2, FALSE, FALSE,
3965 Xacid_3, FALSE, FALSE,
3969 Xacid_4, FALSE, FALSE,
3973 Xacid_5, FALSE, FALSE,
3977 Xacid_6, FALSE, FALSE,
3981 Xacid_7, FALSE, FALSE,
3985 Xacid_8, FALSE, FALSE,
3989 Xball_1, TRUE, FALSE,
3990 EL_EMC_MAGIC_BALL, -1, -1
3993 Xball_1B, FALSE, FALSE,
3994 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
3997 Xball_2, FALSE, FALSE,
3998 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
4001 Xball_2B, FALSE, FALSE,
4002 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
4005 Yball_eat, FALSE, FALSE,
4006 EL_EMC_MAGIC_BALL, ACTION_DROPPING, -1
4009 Ykey_1_eat, FALSE, FALSE,
4010 EL_EM_KEY_1, ACTION_COLLECTING, -1
4013 Ykey_2_eat, FALSE, FALSE,
4014 EL_EM_KEY_2, ACTION_COLLECTING, -1
4017 Ykey_3_eat, FALSE, FALSE,
4018 EL_EM_KEY_3, ACTION_COLLECTING, -1
4021 Ykey_4_eat, FALSE, FALSE,
4022 EL_EM_KEY_4, ACTION_COLLECTING, -1
4025 Ykey_5_eat, FALSE, FALSE,
4026 EL_EMC_KEY_5, ACTION_COLLECTING, -1
4029 Ykey_6_eat, FALSE, FALSE,
4030 EL_EMC_KEY_6, ACTION_COLLECTING, -1
4033 Ykey_7_eat, FALSE, FALSE,
4034 EL_EMC_KEY_7, ACTION_COLLECTING, -1
4037 Ykey_8_eat, FALSE, FALSE,
4038 EL_EMC_KEY_8, ACTION_COLLECTING, -1
4041 Ylenses_eat, FALSE, FALSE,
4042 EL_EMC_LENSES, ACTION_COLLECTING, -1
4045 Ymagnify_eat, FALSE, FALSE,
4046 EL_EMC_MAGNIFIER, ACTION_COLLECTING, -1
4049 Ygrass_eat, FALSE, FALSE,
4050 EL_EMC_GRASS, ACTION_SNAPPING, -1
4053 Ydirt_eat, FALSE, FALSE,
4054 EL_SAND, ACTION_SNAPPING, -1
4057 Xgrow_ns, TRUE, FALSE,
4058 EL_EXPANDABLE_WALL_VERTICAL, -1, -1
4061 Ygrow_ns_eat, FALSE, FALSE,
4062 EL_EXPANDABLE_WALL_VERTICAL, ACTION_GROWING, -1
4065 Xgrow_ew, TRUE, FALSE,
4066 EL_EXPANDABLE_WALL_HORIZONTAL, -1, -1
4069 Ygrow_ew_eat, FALSE, FALSE,
4070 EL_EXPANDABLE_WALL_HORIZONTAL, ACTION_GROWING, -1
4073 Xwonderwall, TRUE, FALSE,
4074 EL_MAGIC_WALL, -1, -1
4077 XwonderwallB, FALSE, FALSE,
4078 EL_MAGIC_WALL, ACTION_ACTIVE, -1
4081 Xamoeba_1, TRUE, FALSE,
4082 EL_AMOEBA_DRY, ACTION_OTHER, -1
4085 Xamoeba_2, FALSE, FALSE,
4086 EL_AMOEBA_DRY, ACTION_OTHER, -1
4089 Xamoeba_3, FALSE, FALSE,
4090 EL_AMOEBA_DRY, ACTION_OTHER, -1
4093 Xamoeba_4, FALSE, FALSE,
4094 EL_AMOEBA_DRY, ACTION_OTHER, -1
4097 Xamoeba_5, TRUE, FALSE,
4098 EL_AMOEBA_WET, ACTION_OTHER, -1
4101 Xamoeba_6, FALSE, FALSE,
4102 EL_AMOEBA_WET, ACTION_OTHER, -1
4105 Xamoeba_7, FALSE, FALSE,
4106 EL_AMOEBA_WET, ACTION_OTHER, -1
4109 Xamoeba_8, FALSE, FALSE,
4110 EL_AMOEBA_WET, ACTION_OTHER, -1
4113 Xdoor_1, TRUE, FALSE,
4114 EL_EM_GATE_1, -1, -1
4117 Xdoor_2, TRUE, FALSE,
4118 EL_EM_GATE_2, -1, -1
4121 Xdoor_3, TRUE, FALSE,
4122 EL_EM_GATE_3, -1, -1
4125 Xdoor_4, TRUE, FALSE,
4126 EL_EM_GATE_4, -1, -1
4129 Xdoor_5, TRUE, FALSE,
4130 EL_EMC_GATE_5, -1, -1
4133 Xdoor_6, TRUE, FALSE,
4134 EL_EMC_GATE_6, -1, -1
4137 Xdoor_7, TRUE, FALSE,
4138 EL_EMC_GATE_7, -1, -1
4141 Xdoor_8, TRUE, FALSE,
4142 EL_EMC_GATE_8, -1, -1
4145 Xkey_1, TRUE, FALSE,
4149 Xkey_2, TRUE, FALSE,
4153 Xkey_3, TRUE, FALSE,
4157 Xkey_4, TRUE, FALSE,
4161 Xkey_5, TRUE, FALSE,
4162 EL_EMC_KEY_5, -1, -1
4165 Xkey_6, TRUE, FALSE,
4166 EL_EMC_KEY_6, -1, -1
4169 Xkey_7, TRUE, FALSE,
4170 EL_EMC_KEY_7, -1, -1
4173 Xkey_8, TRUE, FALSE,
4174 EL_EMC_KEY_8, -1, -1
4177 Xwind_n, TRUE, FALSE,
4178 EL_BALLOON_SWITCH_UP, -1, -1
4181 Xwind_e, TRUE, FALSE,
4182 EL_BALLOON_SWITCH_RIGHT, -1, -1
4185 Xwind_s, TRUE, FALSE,
4186 EL_BALLOON_SWITCH_DOWN, -1, -1
4189 Xwind_w, TRUE, FALSE,
4190 EL_BALLOON_SWITCH_LEFT, -1, -1
4193 Xwind_nesw, TRUE, FALSE,
4194 EL_BALLOON_SWITCH_ANY, -1, -1
4197 Xwind_stop, TRUE, FALSE,
4198 EL_BALLOON_SWITCH_NONE, -1, -1
4202 EL_EXIT_CLOSED, -1, -1
4205 Xexit_1, TRUE, FALSE,
4206 EL_EXIT_OPEN, -1, -1
4209 Xexit_2, FALSE, FALSE,
4210 EL_EXIT_OPEN, -1, -1
4213 Xexit_3, FALSE, FALSE,
4214 EL_EXIT_OPEN, -1, -1
4217 Xdynamite, TRUE, FALSE,
4221 Ydynamite_eat, FALSE, FALSE,
4222 EL_DYNAMITE, ACTION_COLLECTING, -1
4225 Xdynamite_1, TRUE, FALSE,
4226 EL_DYNAMITE_ACTIVE, -1, -1
4229 Xdynamite_2, FALSE, FALSE,
4230 EL_DYNAMITE_ACTIVE, -1, -1
4233 Xdynamite_3, FALSE, FALSE,
4234 EL_DYNAMITE_ACTIVE, -1, -1
4237 Xdynamite_4, FALSE, FALSE,
4238 EL_DYNAMITE_ACTIVE, -1, -1
4241 Xbumper, TRUE, FALSE,
4242 EL_EMC_SPRING_BUMPER, -1, -1
4245 XbumperB, FALSE, FALSE,
4246 EL_EMC_SPRING_BUMPER, ACTION_ACTIVE, -1
4249 Xwheel, TRUE, FALSE,
4250 EL_ROBOT_WHEEL, -1, -1
4253 XwheelB, FALSE, FALSE,
4254 EL_ROBOT_WHEEL, ACTION_ACTIVE, -1
4257 Xswitch, TRUE, FALSE,
4258 EL_EMC_MAGIC_BALL_SWITCH, -1, -1
4261 XswitchB, FALSE, FALSE,
4262 EL_EMC_MAGIC_BALL_SWITCH, ACTION_ACTIVE, -1
4266 EL_QUICKSAND_EMPTY, -1, -1
4269 Xsand_stone, TRUE, FALSE,
4270 EL_QUICKSAND_FULL, -1, -1
4273 Xsand_stonein_1, FALSE, FALSE,
4274 EL_ROCK, ACTION_FILLING, -1
4277 Xsand_stonein_2, FALSE, FALSE,
4278 EL_ROCK, ACTION_FILLING, -1
4281 Xsand_stonein_3, FALSE, FALSE,
4282 EL_ROCK, ACTION_FILLING, -1
4285 Xsand_stonein_4, FALSE, FALSE,
4286 EL_ROCK, ACTION_FILLING, -1
4289 Xsand_stonesand_1, FALSE, FALSE,
4290 EL_QUICKSAND_FULL, -1, -1
4293 Xsand_stonesand_2, FALSE, FALSE,
4294 EL_QUICKSAND_FULL, -1, -1
4297 Xsand_stonesand_3, FALSE, FALSE,
4298 EL_QUICKSAND_FULL, -1, -1
4301 Xsand_stonesand_4, FALSE, FALSE,
4302 EL_QUICKSAND_FULL, -1, -1
4305 Xsand_stoneout_1, FALSE, FALSE,
4306 EL_ROCK, ACTION_EMPTYING, -1
4309 Xsand_stoneout_2, FALSE, FALSE,
4310 EL_ROCK, ACTION_EMPTYING, -1
4313 Xsand_sandstone_1, FALSE, FALSE,
4314 EL_QUICKSAND_FULL, -1, -1
4317 Xsand_sandstone_2, FALSE, FALSE,
4318 EL_QUICKSAND_FULL, -1, -1
4321 Xsand_sandstone_3, FALSE, FALSE,
4322 EL_QUICKSAND_FULL, -1, -1
4325 Xsand_sandstone_4, FALSE, FALSE,
4326 EL_QUICKSAND_FULL, -1, -1
4329 Xplant, TRUE, FALSE,
4330 EL_EMC_PLANT, -1, -1
4333 Yplant, FALSE, FALSE,
4334 EL_EMC_PLANT, -1, -1
4337 Xlenses, TRUE, FALSE,
4338 EL_EMC_LENSES, -1, -1
4341 Xmagnify, TRUE, FALSE,
4342 EL_EMC_MAGNIFIER, -1, -1
4345 Xdripper, TRUE, FALSE,
4346 EL_EMC_DRIPPER, -1, -1
4349 XdripperB, FALSE, FALSE,
4350 EL_EMC_DRIPPER, ACTION_ACTIVE, -1
4353 Xfake_blank, TRUE, FALSE,
4354 EL_INVISIBLE_WALL, -1, -1
4357 Xfake_blankB, FALSE, FALSE,
4358 EL_INVISIBLE_WALL, ACTION_ACTIVE, -1
4361 Xfake_grass, TRUE, FALSE,
4362 EL_EMC_FAKE_GRASS, -1, -1
4365 Xfake_grassB, FALSE, FALSE,
4366 EL_EMC_FAKE_GRASS, ACTION_ACTIVE, -1
4369 Xfake_door_1, TRUE, FALSE,
4370 EL_EM_GATE_1_GRAY, -1, -1
4373 Xfake_door_2, TRUE, FALSE,
4374 EL_EM_GATE_2_GRAY, -1, -1
4377 Xfake_door_3, TRUE, FALSE,
4378 EL_EM_GATE_3_GRAY, -1, -1
4381 Xfake_door_4, TRUE, FALSE,
4382 EL_EM_GATE_4_GRAY, -1, -1
4385 Xfake_door_5, TRUE, FALSE,
4386 EL_EMC_GATE_5_GRAY, -1, -1
4389 Xfake_door_6, TRUE, FALSE,
4390 EL_EMC_GATE_6_GRAY, -1, -1
4393 Xfake_door_7, TRUE, FALSE,
4394 EL_EMC_GATE_7_GRAY, -1, -1
4397 Xfake_door_8, TRUE, FALSE,
4398 EL_EMC_GATE_8_GRAY, -1, -1
4401 Xfake_acid_1, TRUE, FALSE,
4402 EL_EMC_FAKE_ACID, -1, -1
4405 Xfake_acid_2, FALSE, FALSE,
4406 EL_EMC_FAKE_ACID, -1, -1
4409 Xfake_acid_3, FALSE, FALSE,
4410 EL_EMC_FAKE_ACID, -1, -1
4413 Xfake_acid_4, FALSE, FALSE,
4414 EL_EMC_FAKE_ACID, -1, -1
4417 Xfake_acid_5, FALSE, FALSE,
4418 EL_EMC_FAKE_ACID, -1, -1
4421 Xfake_acid_6, FALSE, FALSE,
4422 EL_EMC_FAKE_ACID, -1, -1
4425 Xfake_acid_7, FALSE, FALSE,
4426 EL_EMC_FAKE_ACID, -1, -1
4429 Xfake_acid_8, FALSE, FALSE,
4430 EL_EMC_FAKE_ACID, -1, -1
4433 Xsteel_1, TRUE, FALSE,
4434 EL_STEELWALL, -1, -1
4437 Xsteel_2, TRUE, FALSE,
4438 EL_EMC_STEELWALL_2, -1, -1
4441 Xsteel_3, TRUE, FALSE,
4442 EL_EMC_STEELWALL_3, -1, -1
4445 Xsteel_4, TRUE, FALSE,
4446 EL_EMC_STEELWALL_4, -1, -1
4449 Xwall_1, TRUE, FALSE,
4453 Xwall_2, TRUE, FALSE,
4454 EL_EMC_WALL_14, -1, -1
4457 Xwall_3, TRUE, FALSE,
4458 EL_EMC_WALL_15, -1, -1
4461 Xwall_4, TRUE, FALSE,
4462 EL_EMC_WALL_16, -1, -1
4465 Xround_wall_1, TRUE, FALSE,
4466 EL_WALL_SLIPPERY, -1, -1
4469 Xround_wall_2, TRUE, FALSE,
4470 EL_EMC_WALL_SLIPPERY_2, -1, -1
4473 Xround_wall_3, TRUE, FALSE,
4474 EL_EMC_WALL_SLIPPERY_3, -1, -1
4477 Xround_wall_4, TRUE, FALSE,
4478 EL_EMC_WALL_SLIPPERY_4, -1, -1
4481 Xdecor_1, TRUE, FALSE,
4482 EL_EMC_WALL_8, -1, -1
4485 Xdecor_2, TRUE, FALSE,
4486 EL_EMC_WALL_6, -1, -1
4489 Xdecor_3, TRUE, FALSE,
4490 EL_EMC_WALL_4, -1, -1
4493 Xdecor_4, TRUE, FALSE,
4494 EL_EMC_WALL_7, -1, -1
4497 Xdecor_5, TRUE, FALSE,
4498 EL_EMC_WALL_5, -1, -1
4501 Xdecor_6, TRUE, FALSE,
4502 EL_EMC_WALL_9, -1, -1
4505 Xdecor_7, TRUE, FALSE,
4506 EL_EMC_WALL_10, -1, -1
4509 Xdecor_8, TRUE, FALSE,
4510 EL_EMC_WALL_1, -1, -1
4513 Xdecor_9, TRUE, FALSE,
4514 EL_EMC_WALL_2, -1, -1
4517 Xdecor_10, TRUE, FALSE,
4518 EL_EMC_WALL_3, -1, -1
4521 Xdecor_11, TRUE, FALSE,
4522 EL_EMC_WALL_11, -1, -1
4525 Xdecor_12, TRUE, FALSE,
4526 EL_EMC_WALL_12, -1, -1
4529 Xalpha_0, TRUE, FALSE,
4530 EL_CHAR('0'), -1, -1
4533 Xalpha_1, TRUE, FALSE,
4534 EL_CHAR('1'), -1, -1
4537 Xalpha_2, TRUE, FALSE,
4538 EL_CHAR('2'), -1, -1
4541 Xalpha_3, TRUE, FALSE,
4542 EL_CHAR('3'), -1, -1
4545 Xalpha_4, TRUE, FALSE,
4546 EL_CHAR('4'), -1, -1
4549 Xalpha_5, TRUE, FALSE,
4550 EL_CHAR('5'), -1, -1
4553 Xalpha_6, TRUE, FALSE,
4554 EL_CHAR('6'), -1, -1
4557 Xalpha_7, TRUE, FALSE,
4558 EL_CHAR('7'), -1, -1
4561 Xalpha_8, TRUE, FALSE,
4562 EL_CHAR('8'), -1, -1
4565 Xalpha_9, TRUE, FALSE,
4566 EL_CHAR('9'), -1, -1
4569 Xalpha_excla, TRUE, FALSE,
4570 EL_CHAR('!'), -1, -1
4573 Xalpha_quote, TRUE, FALSE,
4574 EL_CHAR('"'), -1, -1
4577 Xalpha_comma, TRUE, FALSE,
4578 EL_CHAR(','), -1, -1
4581 Xalpha_minus, TRUE, FALSE,
4582 EL_CHAR('-'), -1, -1
4585 Xalpha_perio, TRUE, FALSE,
4586 EL_CHAR('.'), -1, -1
4589 Xalpha_colon, TRUE, FALSE,
4590 EL_CHAR(':'), -1, -1
4593 Xalpha_quest, TRUE, FALSE,
4594 EL_CHAR('?'), -1, -1
4597 Xalpha_a, TRUE, FALSE,
4598 EL_CHAR('A'), -1, -1
4601 Xalpha_b, TRUE, FALSE,
4602 EL_CHAR('B'), -1, -1
4605 Xalpha_c, TRUE, FALSE,
4606 EL_CHAR('C'), -1, -1
4609 Xalpha_d, TRUE, FALSE,
4610 EL_CHAR('D'), -1, -1
4613 Xalpha_e, TRUE, FALSE,
4614 EL_CHAR('E'), -1, -1
4617 Xalpha_f, TRUE, FALSE,
4618 EL_CHAR('F'), -1, -1
4621 Xalpha_g, TRUE, FALSE,
4622 EL_CHAR('G'), -1, -1
4625 Xalpha_h, TRUE, FALSE,
4626 EL_CHAR('H'), -1, -1
4629 Xalpha_i, TRUE, FALSE,
4630 EL_CHAR('I'), -1, -1
4633 Xalpha_j, TRUE, FALSE,
4634 EL_CHAR('J'), -1, -1
4637 Xalpha_k, TRUE, FALSE,
4638 EL_CHAR('K'), -1, -1
4641 Xalpha_l, TRUE, FALSE,
4642 EL_CHAR('L'), -1, -1
4645 Xalpha_m, TRUE, FALSE,
4646 EL_CHAR('M'), -1, -1
4649 Xalpha_n, TRUE, FALSE,
4650 EL_CHAR('N'), -1, -1
4653 Xalpha_o, TRUE, FALSE,
4654 EL_CHAR('O'), -1, -1
4657 Xalpha_p, TRUE, FALSE,
4658 EL_CHAR('P'), -1, -1
4661 Xalpha_q, TRUE, FALSE,
4662 EL_CHAR('Q'), -1, -1
4665 Xalpha_r, TRUE, FALSE,
4666 EL_CHAR('R'), -1, -1
4669 Xalpha_s, TRUE, FALSE,
4670 EL_CHAR('S'), -1, -1
4673 Xalpha_t, TRUE, FALSE,
4674 EL_CHAR('T'), -1, -1
4677 Xalpha_u, TRUE, FALSE,
4678 EL_CHAR('U'), -1, -1
4681 Xalpha_v, TRUE, FALSE,
4682 EL_CHAR('V'), -1, -1
4685 Xalpha_w, TRUE, FALSE,
4686 EL_CHAR('W'), -1, -1
4689 Xalpha_x, TRUE, FALSE,
4690 EL_CHAR('X'), -1, -1
4693 Xalpha_y, TRUE, FALSE,
4694 EL_CHAR('Y'), -1, -1
4697 Xalpha_z, TRUE, FALSE,
4698 EL_CHAR('Z'), -1, -1
4701 Xalpha_arrow_e, TRUE, FALSE,
4702 EL_CHAR('>'), -1, -1
4705 Xalpha_arrow_w, TRUE, FALSE,
4706 EL_CHAR('<'), -1, -1
4709 Xalpha_copyr, TRUE, FALSE,
4710 EL_CHAR('©'), -1, -1
4713 Xalpha_copyr, TRUE, FALSE,
4714 EL_CHAR('©'), -1, -1
4718 Xboom_bug, FALSE, FALSE,
4719 EL_BUG, ACTION_EXPLODING, -1
4722 Xboom_bomb, FALSE, FALSE,
4723 EL_BOMB, ACTION_EXPLODING, -1
4726 Xboom_android, FALSE, FALSE,
4727 EL_EMC_ANDROID, ACTION_OTHER, -1
4730 Xboom_1, FALSE, FALSE,
4731 EL_DEFAULT, ACTION_EXPLODING, -1
4734 Xboom_2, FALSE, FALSE,
4735 EL_DEFAULT, ACTION_EXPLODING, -1
4738 Znormal, FALSE, FALSE,
4742 Zdynamite, FALSE, FALSE,
4746 Zplayer, FALSE, FALSE,
4750 ZBORDER, FALSE, FALSE,
4760 static struct Mapping_EM_to_RND_player
4769 em_player_mapping_list[] =
4773 EL_PLAYER_1, ACTION_MOVING, MV_BIT_UP,
4777 EL_PLAYER_1, ACTION_MOVING, MV_BIT_RIGHT,
4781 EL_PLAYER_1, ACTION_MOVING, MV_BIT_DOWN,
4785 EL_PLAYER_1, ACTION_MOVING, MV_BIT_LEFT,
4789 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_UP,
4793 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_RIGHT,
4797 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_DOWN,
4801 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_LEFT,
4805 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_UP,
4809 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_RIGHT,
4813 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_DOWN,
4817 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_LEFT,
4821 EL_PLAYER_2, ACTION_MOVING, MV_BIT_UP,
4825 EL_PLAYER_2, ACTION_MOVING, MV_BIT_RIGHT,
4829 EL_PLAYER_2, ACTION_MOVING, MV_BIT_DOWN,
4833 EL_PLAYER_2, ACTION_MOVING, MV_BIT_LEFT,
4837 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_UP,
4841 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_RIGHT,
4845 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_DOWN,
4849 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_LEFT,
4853 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_UP,
4857 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_RIGHT,
4861 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_DOWN,
4865 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_LEFT,
4869 EL_PLAYER_1, ACTION_DEFAULT, -1,
4873 EL_PLAYER_2, ACTION_DEFAULT, -1,
4882 int map_element_RND_to_EM(int element_rnd)
4884 static unsigned short mapping_RND_to_EM[NUM_FILE_ELEMENTS];
4885 static boolean mapping_initialized = FALSE;
4887 if (!mapping_initialized)
4891 /* return "Xalpha_quest" for all undefined elements in mapping array */
4892 for (i = 0; i < NUM_FILE_ELEMENTS; i++)
4893 mapping_RND_to_EM[i] = Xalpha_quest;
4895 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
4896 if (em_object_mapping_list[i].is_rnd_to_em_mapping)
4897 mapping_RND_to_EM[em_object_mapping_list[i].element_rnd] =
4898 em_object_mapping_list[i].element_em;
4900 mapping_initialized = TRUE;
4903 if (element_rnd >= 0 && element_rnd < NUM_FILE_ELEMENTS)
4904 return mapping_RND_to_EM[element_rnd];
4906 Error(ERR_WARN, "invalid RND level element %d", element_rnd);
4911 int map_element_EM_to_RND(int element_em)
4913 static unsigned short mapping_EM_to_RND[TILE_MAX];
4914 static boolean mapping_initialized = FALSE;
4916 if (!mapping_initialized)
4920 /* return "EL_UNKNOWN" for all undefined elements in mapping array */
4921 for (i = 0; i < TILE_MAX; i++)
4922 mapping_EM_to_RND[i] = EL_UNKNOWN;
4924 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
4925 mapping_EM_to_RND[em_object_mapping_list[i].element_em] =
4926 em_object_mapping_list[i].element_rnd;
4928 mapping_initialized = TRUE;
4931 if (element_em >= 0 && element_em < TILE_MAX)
4932 return mapping_EM_to_RND[element_em];
4934 Error(ERR_WARN, "invalid EM level element %d", element_em);
4941 int map_element_RND_to_EM(int element_rnd)
4943 static unsigned short mapping_RND_to_EM[NUM_FILE_ELEMENTS];
4944 static boolean mapping_initialized = FALSE;
4951 mapping_RND_to_EM_list[] =
4953 { Xblank, EL_EMPTY },
4954 { Xstone, EL_ROCK },
4956 { Xbug_n, EL_BUG_UP },
4957 { Xbug_e, EL_BUG_RIGHT },
4958 { Xbug_s, EL_BUG_DOWN },
4959 { Xbug_w, EL_BUG_LEFT },
4960 { Xtank_n, EL_SPACESHIP_UP },
4961 { Xtank_e, EL_SPACESHIP_RIGHT },
4962 { Xtank_s, EL_SPACESHIP_DOWN },
4963 { Xtank_w, EL_SPACESHIP_LEFT },
4964 { Xandroid, EL_EMC_ANDROID },
4965 { Xandroid_1_n, EL_EMC_ANDROID_UP },
4966 { Xandroid_1_e, EL_EMC_ANDROID_RIGHT },
4967 { Xandroid_1_w, EL_EMC_ANDROID_LEFT },
4968 { Xandroid_1_s, EL_EMC_ANDROID_DOWN },
4969 { Xspring, EL_SPRING },
4970 { Xeater_n, EL_YAMYAM },
4971 { Xalien, EL_ROBOT },
4972 { Xemerald, EL_EMERALD },
4973 { Xdiamond, EL_DIAMOND },
4974 { Xdrip_fall, EL_AMOEBA_DROP },
4976 { Xballoon, EL_BALLOON },
4977 { Xgrass, EL_EMC_GRASS },
4979 { Xacid_ne, EL_ACID_POOL_TOPRIGHT },
4980 { Xacid_se, EL_ACID_POOL_BOTTOMRIGHT },
4981 { Xacid_s, EL_ACID_POOL_BOTTOM },
4982 { Xacid_sw, EL_ACID_POOL_BOTTOMLEFT },
4983 { Xacid_nw, EL_ACID_POOL_TOPLEFT },
4984 { Xacid_1, EL_ACID },
4985 { Xball_1, EL_EMC_MAGIC_BALL },
4986 { Xgrow_ns, EL_EMC_GROW },
4987 { Xwonderwall, EL_MAGIC_WALL },
4988 { Xamoeba_1, EL_AMOEBA_WET },
4989 { Xdoor_1, EL_EM_GATE_1 },
4990 { Xdoor_2, EL_EM_GATE_2 },
4991 { Xdoor_3, EL_EM_GATE_3 },
4992 { Xdoor_4, EL_EM_GATE_4 },
4993 { Xdoor_5, EL_EMC_GATE_5 },
4994 { Xdoor_6, EL_EMC_GATE_6 },
4995 { Xdoor_7, EL_EMC_GATE_7 },
4996 { Xdoor_8, EL_EMC_GATE_8 },
4997 { Xkey_1, EL_EM_KEY_1 },
4998 { Xkey_2, EL_EM_KEY_2 },
4999 { Xkey_3, EL_EM_KEY_3 },
5000 { Xkey_4, EL_EM_KEY_4 },
5001 { Xkey_5, EL_EMC_KEY_5 },
5002 { Xkey_6, EL_EMC_KEY_6 },
5003 { Xkey_7, EL_EMC_KEY_7 },
5004 { Xkey_8, EL_EMC_KEY_8 },
5005 { Xwind_n, EL_BALLOON_SWITCH_UP },
5006 { Xwind_e, EL_BALLOON_SWITCH_RIGHT },
5007 { Xwind_s, EL_BALLOON_SWITCH_DOWN },
5008 { Xwind_w, EL_BALLOON_SWITCH_LEFT },
5009 { Xwind_nesw, EL_BALLOON_SWITCH_ANY },
5010 { Xwind_stop, EL_BALLOON_SWITCH_NONE },
5011 { Xexit, EL_EXIT_CLOSED },
5012 { Xexit_1, EL_EXIT_OPEN },
5013 { Xdynamite, EL_DYNAMITE },
5014 { Xdynamite_1, EL_DYNAMITE_ACTIVE },
5015 { Xbumper, EL_EMC_BUMPER },
5016 { Xwheel, EL_ROBOT_WHEEL },
5017 { Xswitch, EL_UNKNOWN },
5018 { Xsand, EL_QUICKSAND_EMPTY },
5019 { Xsand_stone, EL_QUICKSAND_FULL },
5020 { Xplant, EL_EMC_PLANT },
5021 { Xlenses, EL_EMC_LENSES },
5022 { Xmagnify, EL_EMC_MAGNIFIER },
5023 { Xdripper, EL_UNKNOWN },
5024 { Xfake_blank, EL_INVISIBLE_WALL },
5025 { Xfake_grass, EL_INVISIBLE_SAND },
5026 { Xfake_door_1, EL_EM_GATE_1_GRAY },
5027 { Xfake_door_2, EL_EM_GATE_2_GRAY },
5028 { Xfake_door_3, EL_EM_GATE_3_GRAY },
5029 { Xfake_door_4, EL_EM_GATE_4_GRAY },
5030 { Xfake_door_5, EL_EMC_GATE_5_GRAY },
5031 { Xfake_door_6, EL_EMC_GATE_6_GRAY },
5032 { Xfake_door_7, EL_EMC_GATE_7_GRAY },
5033 { Xfake_door_8, EL_EMC_GATE_8_GRAY },
5034 { Xsteel_1, EL_STEELWALL },
5035 { Xsteel_2, EL_UNKNOWN },
5036 { Xsteel_3, EL_EMC_STEELWALL_1 },
5037 { Xsteel_4, EL_UNKNOWN },
5038 { Xwall_1, EL_WALL },
5039 { Xwall_2, EL_UNKNOWN },
5040 { Xwall_3, EL_UNKNOWN },
5041 { Xwall_4, EL_UNKNOWN },
5042 { Xround_wall_1, EL_WALL_SLIPPERY },
5043 { Xround_wall_2, EL_UNKNOWN },
5044 { Xround_wall_3, EL_UNKNOWN },
5045 { Xround_wall_4, EL_UNKNOWN },
5046 { Xdecor_1, EL_UNKNOWN },
5047 { Xdecor_2, EL_EMC_WALL_6 },
5048 { Xdecor_3, EL_EMC_WALL_4 },
5049 { Xdecor_4, EL_EMC_WALL_5 },
5050 { Xdecor_5, EL_EMC_WALL_7 },
5051 { Xdecor_6, EL_EMC_WALL_8 },
5052 { Xdecor_7, EL_UNKNOWN },
5053 { Xdecor_8, EL_EMC_WALL_1 },
5054 { Xdecor_9, EL_EMC_WALL_2 },
5055 { Xdecor_10, EL_EMC_WALL_3 },
5056 { Xdecor_11, EL_UNKNOWN },
5057 { Xdecor_12, EL_UNKNOWN },
5058 { Xalpha_0, EL_CHAR('0') },
5059 { Xalpha_1, EL_CHAR('1') },
5060 { Xalpha_2, EL_CHAR('2') },
5061 { Xalpha_3, EL_CHAR('3') },
5062 { Xalpha_4, EL_CHAR('4') },
5063 { Xalpha_5, EL_CHAR('5') },
5064 { Xalpha_6, EL_CHAR('6') },
5065 { Xalpha_7, EL_CHAR('7') },
5066 { Xalpha_8, EL_CHAR('8') },
5067 { Xalpha_9, EL_CHAR('9') },
5068 { Xalpha_excla, EL_CHAR('!') },
5069 { Xalpha_quote, EL_CHAR('"') },
5070 { Xalpha_comma, EL_CHAR(',') },
5071 { Xalpha_minus, EL_CHAR('-') },
5072 { Xalpha_perio, EL_CHAR('.') },
5073 { Xalpha_colon, EL_CHAR(':') },
5074 { Xalpha_quest, EL_CHAR('?') },
5075 { Xalpha_a, EL_CHAR('A') },
5076 { Xalpha_b, EL_CHAR('B') },
5077 { Xalpha_c, EL_CHAR('C') },
5078 { Xalpha_d, EL_CHAR('D') },
5079 { Xalpha_e, EL_CHAR('E') },
5080 { Xalpha_f, EL_CHAR('F') },
5081 { Xalpha_g, EL_CHAR('G') },
5082 { Xalpha_h, EL_CHAR('H') },
5083 { Xalpha_i, EL_CHAR('I') },
5084 { Xalpha_j, EL_CHAR('J') },
5085 { Xalpha_k, EL_CHAR('K') },
5086 { Xalpha_l, EL_CHAR('L') },
5087 { Xalpha_m, EL_CHAR('M') },
5088 { Xalpha_n, EL_CHAR('N') },
5089 { Xalpha_o, EL_CHAR('O') },
5090 { Xalpha_p, EL_CHAR('P') },
5091 { Xalpha_q, EL_CHAR('Q') },
5092 { Xalpha_r, EL_CHAR('R') },
5093 { Xalpha_s, EL_CHAR('S') },
5094 { Xalpha_t, EL_CHAR('T') },
5095 { Xalpha_u, EL_CHAR('U') },
5096 { Xalpha_v, EL_CHAR('V') },
5097 { Xalpha_w, EL_CHAR('W') },
5098 { Xalpha_x, EL_CHAR('X') },
5099 { Xalpha_y, EL_CHAR('Y') },
5100 { Xalpha_z, EL_CHAR('Z') },
5101 { Xalpha_arrow_e, EL_CHAR('>') },
5102 { Xalpha_arrow_w, EL_CHAR('<') },
5103 { Xalpha_copyr, EL_CHAR('©') },
5105 { Zplayer, EL_PLAYER_1 },
5106 { Zplayer, EL_PLAYER_2 },
5107 { Zplayer, EL_PLAYER_3 },
5108 { Zplayer, EL_PLAYER_4 },
5110 { ZBORDER, EL_EMC_LEVEL_BORDER },
5115 if (!mapping_initialized)
5119 /* return "Xalpha_quest" for all undefined elements in mapping array */
5120 for (i = 0; i < NUM_FILE_ELEMENTS; i++)
5121 mapping_RND_to_EM[i] = Xalpha_quest;
5123 for (i = 0; mapping_RND_to_EM_list[i].element_rnd != -1; i++)
5124 mapping_RND_to_EM[mapping_RND_to_EM_list[i].element_rnd] =
5125 mapping_RND_to_EM_list[i].element_em;
5127 mapping_initialized = TRUE;
5130 if (element_rnd >= 0 && element_rnd < NUM_FILE_ELEMENTS)
5131 return mapping_RND_to_EM[element_rnd];
5133 Error(ERR_WARN, "invalid RND level element %d", element_rnd);
5138 int map_element_EM_to_RND(int element_em)
5140 static unsigned short mapping_EM_to_RND[TILE_MAX];
5141 static boolean mapping_initialized = FALSE;
5148 em_object_mapping_list[] =
5150 { Xblank, EL_EMPTY },
5151 { Yacid_splash_eB, EL_EMPTY },
5152 { Yacid_splash_wB, EL_EMPTY },
5154 #ifdef EM_ENGINE_BAD_ROLL
5155 { Xstone_force_e, EL_ROCK },
5156 { Xstone_force_w, EL_ROCK },
5157 { Xnut_force_e, EL_NUT },
5158 { Xnut_force_w, EL_NUT },
5159 { Xspring_force_e, EL_SPRING },
5160 { Xspring_force_w, EL_SPRING },
5161 { Xemerald_force_e, EL_EMERALD },
5162 { Xemerald_force_w, EL_EMERALD },
5163 { Xdiamond_force_e, EL_DIAMOND },
5164 { Xdiamond_force_w, EL_DIAMOND },
5165 { Xbomb_force_e, EL_BOMB },
5166 { Xbomb_force_w, EL_BOMB },
5169 { Xstone, EL_ROCK },
5170 { Xstone_pause, EL_ROCK },
5171 { Xstone_fall, EL_ROCK },
5172 { Ystone_s, EL_ROCK },
5173 { Ystone_sB, EL_ROCK },
5174 { Ystone_e, EL_ROCK },
5175 { Ystone_eB, EL_ROCK },
5176 { Ystone_w, EL_ROCK },
5177 { Ystone_wB, EL_ROCK },
5179 { Xnut_pause, EL_NUT },
5180 { Xnut_fall, EL_NUT },
5182 { Ynut_sB, EL_NUT },
5184 { Ynut_eB, EL_NUT },
5186 { Ynut_wB, EL_NUT },
5187 { Xbug_n, EL_BUG_UP },
5188 { Xbug_e, EL_BUG_RIGHT },
5189 { Xbug_s, EL_BUG_DOWN },
5190 { Xbug_w, EL_BUG_LEFT },
5191 { Xbug_gon, EL_BUG_UP },
5192 { Xbug_goe, EL_BUG_RIGHT },
5193 { Xbug_gos, EL_BUG_DOWN },
5194 { Xbug_gow, EL_BUG_LEFT },
5195 { Ybug_n, EL_BUG_UP },
5196 { Ybug_nB, EL_BUG_UP },
5197 { Ybug_e, EL_BUG_RIGHT },
5198 { Ybug_eB, EL_BUG_RIGHT },
5199 { Ybug_s, EL_BUG_DOWN },
5200 { Ybug_sB, EL_BUG_DOWN },
5201 { Ybug_w, EL_BUG_LEFT },
5202 { Ybug_wB, EL_BUG_LEFT },
5203 { Ybug_w_n, EL_BUG_UP },
5204 { Ybug_n_e, EL_BUG_RIGHT },
5205 { Ybug_e_s, EL_BUG_DOWN },
5206 { Ybug_s_w, EL_BUG_LEFT },
5207 { Ybug_e_n, EL_BUG_UP },
5208 { Ybug_s_e, EL_BUG_RIGHT },
5209 { Ybug_w_s, EL_BUG_DOWN },
5210 { Ybug_n_w, EL_BUG_LEFT },
5211 { Ybug_stone, EL_ROCK },
5212 { Ybug_spring, EL_SPRING },
5213 { Xtank_n, EL_SPACESHIP_UP },
5214 { Xtank_e, EL_SPACESHIP_RIGHT },
5215 { Xtank_s, EL_SPACESHIP_DOWN },
5216 { Xtank_w, EL_SPACESHIP_LEFT },
5217 { Xtank_gon, EL_SPACESHIP_UP },
5218 { Xtank_goe, EL_SPACESHIP_RIGHT },
5219 { Xtank_gos, EL_SPACESHIP_DOWN },
5220 { Xtank_gow, EL_SPACESHIP_LEFT },
5221 { Ytank_n, EL_SPACESHIP_UP },
5222 { Ytank_nB, EL_SPACESHIP_UP },
5223 { Ytank_e, EL_SPACESHIP_RIGHT },
5224 { Ytank_eB, EL_SPACESHIP_RIGHT },
5225 { Ytank_s, EL_SPACESHIP_DOWN },
5226 { Ytank_sB, EL_SPACESHIP_DOWN },
5227 { Ytank_w, EL_SPACESHIP_LEFT },
5228 { Ytank_wB, EL_SPACESHIP_LEFT },
5229 { Ytank_w_n, EL_SPACESHIP_UP },
5230 { Ytank_n_e, EL_SPACESHIP_RIGHT },
5231 { Ytank_e_s, EL_SPACESHIP_DOWN },
5232 { Ytank_s_w, EL_SPACESHIP_LEFT },
5233 { Ytank_e_n, EL_SPACESHIP_UP },
5234 { Ytank_s_e, EL_SPACESHIP_RIGHT },
5235 { Ytank_w_s, EL_SPACESHIP_DOWN },
5236 { Ytank_n_w, EL_SPACESHIP_LEFT },
5237 { Ytank_stone, EL_ROCK },
5238 { Ytank_spring, EL_SPRING },
5239 { Xandroid, EL_EMC_ANDROID },
5240 { Xandroid_1_n, EL_EMC_ANDROID_UP },
5241 { Xandroid_2_n, EL_EMC_ANDROID_UP },
5242 { Xandroid_1_e, EL_EMC_ANDROID_RIGHT },
5243 { Xandroid_2_e, EL_EMC_ANDROID_RIGHT },
5244 { Xandroid_1_w, EL_EMC_ANDROID_LEFT },
5245 { Xandroid_2_w, EL_EMC_ANDROID_LEFT },
5246 { Xandroid_1_s, EL_EMC_ANDROID_DOWN },
5247 { Xandroid_2_s, EL_EMC_ANDROID_DOWN },
5248 { Yandroid_n, EL_EMC_ANDROID_UP },
5249 { Yandroid_nB, EL_EMC_ANDROID_UP },
5250 { Yandroid_ne, EL_EMC_ANDROID_RIGHT_UP },
5251 { Yandroid_neB, EL_EMC_ANDROID_RIGHT_UP },
5252 { Yandroid_e, EL_EMC_ANDROID_RIGHT },
5253 { Yandroid_eB, EL_EMC_ANDROID_RIGHT },
5254 { Yandroid_se, EL_EMC_ANDROID_RIGHT_DOWN },
5255 { Yandroid_seB, EL_EMC_ANDROID_RIGHT_DOWN },
5256 { Yandroid_s, EL_EMC_ANDROID_DOWN },
5257 { Yandroid_sB, EL_EMC_ANDROID_DOWN },
5258 { Yandroid_sw, EL_EMC_ANDROID_LEFT_DOWN },
5259 { Yandroid_swB, EL_EMC_ANDROID_LEFT_DOWN },
5260 { Yandroid_w, EL_EMC_ANDROID_LEFT },
5261 { Yandroid_wB, EL_EMC_ANDROID_LEFT },
5262 { Yandroid_nw, EL_EMC_ANDROID_LEFT_UP },
5263 { Yandroid_nwB, EL_EMC_ANDROID_LEFT_UP },
5264 { Xspring, EL_SPRING },
5265 { Xspring_pause, EL_SPRING },
5266 { Xspring_e, EL_SPRING },
5267 { Xspring_w, EL_SPRING },
5268 { Xspring_fall, EL_SPRING },
5269 { Yspring_s, EL_SPRING },
5270 { Yspring_sB, EL_SPRING },
5271 { Yspring_e, EL_SPRING },
5272 { Yspring_eB, EL_SPRING },
5273 { Yspring_w, EL_SPRING },
5274 { Yspring_wB, EL_SPRING },
5275 { Yspring_kill_e, EL_SPRING },
5276 { Yspring_kill_eB, EL_SPRING },
5277 { Yspring_kill_w, EL_SPRING },
5278 { Yspring_kill_wB, EL_SPRING },
5279 { Xeater_n, EL_YAMYAM },
5280 { Xeater_e, EL_YAMYAM },
5281 { Xeater_w, EL_YAMYAM },
5282 { Xeater_s, EL_YAMYAM },
5283 { Yeater_n, EL_YAMYAM },
5284 { Yeater_nB, EL_YAMYAM },
5285 { Yeater_e, EL_YAMYAM },
5286 { Yeater_eB, EL_YAMYAM },
5287 { Yeater_s, EL_YAMYAM },
5288 { Yeater_sB, EL_YAMYAM },
5289 { Yeater_w, EL_YAMYAM },
5290 { Yeater_wB, EL_YAMYAM },
5291 { Yeater_stone, EL_ROCK },
5292 { Yeater_spring, EL_SPRING },
5293 { Xalien, EL_ROBOT },
5294 { Xalien_pause, EL_ROBOT },
5295 { Yalien_n, EL_ROBOT },
5296 { Yalien_nB, EL_ROBOT },
5297 { Yalien_e, EL_ROBOT },
5298 { Yalien_eB, EL_ROBOT },
5299 { Yalien_s, EL_ROBOT },
5300 { Yalien_sB, EL_ROBOT },
5301 { Yalien_w, EL_ROBOT },
5302 { Yalien_wB, EL_ROBOT },
5303 { Yalien_stone, EL_ROCK },
5304 { Yalien_spring, EL_SPRING },
5305 { Xemerald, EL_EMERALD },
5306 { Xemerald_pause, EL_EMERALD },
5307 { Xemerald_fall, EL_EMERALD },
5308 { Xemerald_shine, EL_EMERALD },
5309 { Yemerald_s, EL_EMERALD },
5310 { Yemerald_sB, EL_EMERALD },
5311 { Yemerald_e, EL_EMERALD },
5312 { Yemerald_eB, EL_EMERALD },
5313 { Yemerald_w, EL_EMERALD },
5314 { Yemerald_wB, EL_EMERALD },
5315 { Yemerald_eat, EL_EMERALD },
5316 { Yemerald_stone, EL_ROCK },
5317 { Xdiamond, EL_DIAMOND },
5318 { Xdiamond_pause, EL_DIAMOND },
5319 { Xdiamond_fall, EL_DIAMOND },
5320 { Xdiamond_shine, EL_DIAMOND },
5321 { Ydiamond_s, EL_DIAMOND },
5322 { Ydiamond_sB, EL_DIAMOND },
5323 { Ydiamond_e, EL_DIAMOND },
5324 { Ydiamond_eB, EL_DIAMOND },
5325 { Ydiamond_w, EL_DIAMOND },
5326 { Ydiamond_wB, EL_DIAMOND },
5327 { Ydiamond_eat, EL_DIAMOND },
5328 { Ydiamond_stone, EL_ROCK },
5329 { Xdrip_fall, EL_AMOEBA_DROP },
5330 { Xdrip_stretch, EL_AMOEBA_DROP },
5331 { Xdrip_stretchB, EL_AMOEBA_DROP },
5332 { Xdrip_eat, EL_AMOEBA_DROP },
5333 { Ydrip_s1, EL_AMOEBA_DROP },
5334 { Ydrip_s1B, EL_AMOEBA_DROP },
5335 { Ydrip_s2, EL_AMOEBA_DROP },
5336 { Ydrip_s2B, EL_AMOEBA_DROP },
5338 { Xbomb_pause, EL_BOMB },
5339 { Xbomb_fall, EL_BOMB },
5340 { Ybomb_s, EL_BOMB },
5341 { Ybomb_sB, EL_BOMB },
5342 { Ybomb_e, EL_BOMB },
5343 { Ybomb_eB, EL_BOMB },
5344 { Ybomb_w, EL_BOMB },
5345 { Ybomb_wB, EL_BOMB },
5346 { Ybomb_eat, EL_BOMB },
5347 { Xballoon, EL_BALLOON },
5348 { Yballoon_n, EL_BALLOON },
5349 { Yballoon_nB, EL_BALLOON },
5350 { Yballoon_e, EL_BALLOON },
5351 { Yballoon_eB, EL_BALLOON },
5352 { Yballoon_s, EL_BALLOON },
5353 { Yballoon_sB, EL_BALLOON },
5354 { Yballoon_w, EL_BALLOON },
5355 { Yballoon_wB, EL_BALLOON },
5356 { Xgrass, EL_SAND },
5357 { Ygrass_nB, EL_SAND },
5358 { Ygrass_eB, EL_SAND },
5359 { Ygrass_sB, EL_SAND },
5360 { Ygrass_wB, EL_SAND },
5362 { Ydirt_nB, EL_SAND },
5363 { Ydirt_eB, EL_SAND },
5364 { Ydirt_sB, EL_SAND },
5365 { Ydirt_wB, EL_SAND },
5366 { Xacid_ne, EL_ACID_POOL_TOPRIGHT },
5367 { Xacid_se, EL_ACID_POOL_BOTTOMRIGHT },
5368 { Xacid_s, EL_ACID_POOL_BOTTOM },
5369 { Xacid_sw, EL_ACID_POOL_BOTTOMLEFT },
5370 { Xacid_nw, EL_ACID_POOL_TOPLEFT },
5371 { Xacid_1, EL_ACID },
5372 { Xacid_2, EL_ACID },
5373 { Xacid_3, EL_ACID },
5374 { Xacid_4, EL_ACID },
5375 { Xacid_5, EL_ACID },
5376 { Xacid_6, EL_ACID },
5377 { Xacid_7, EL_ACID },
5378 { Xacid_8, EL_ACID },
5379 { Xball_1, EL_EMC_MAGIC_BALL },
5380 { Xball_1B, EL_EMC_MAGIC_BALL },
5381 { Xball_2, EL_EMC_MAGIC_BALL },
5382 { Xball_2B, EL_EMC_MAGIC_BALL },
5383 { Yball_eat, EL_EMC_MAGIC_BALL },
5384 { Xgrow_ns, EL_EMC_GROW },
5385 { Ygrow_ns_eat, EL_EMC_GROW },
5386 { Xgrow_ew, EL_EMC_GROW },
5387 { Ygrow_ew_eat, EL_EMC_GROW },
5388 { Xwonderwall, EL_MAGIC_WALL },
5389 { XwonderwallB, EL_MAGIC_WALL },
5390 { Xamoeba_1, EL_AMOEBA_WET },
5391 { Xamoeba_2, EL_AMOEBA_WET },
5392 { Xamoeba_3, EL_AMOEBA_WET },
5393 { Xamoeba_4, EL_AMOEBA_WET },
5394 { Xamoeba_5, EL_AMOEBA_WET },
5395 { Xamoeba_6, EL_AMOEBA_WET },
5396 { Xamoeba_7, EL_AMOEBA_WET },
5397 { Xamoeba_8, EL_AMOEBA_WET },
5398 { Xdoor_1, EL_EM_GATE_1 },
5399 { Xdoor_2, EL_EM_GATE_2 },
5400 { Xdoor_3, EL_EM_GATE_3 },
5401 { Xdoor_4, EL_EM_GATE_4 },
5402 { Xdoor_5, EL_EMC_GATE_5 },
5403 { Xdoor_6, EL_EMC_GATE_6 },
5404 { Xdoor_7, EL_EMC_GATE_7 },
5405 { Xdoor_8, EL_EMC_GATE_8 },
5406 { Xkey_1, EL_EM_KEY_1 },
5407 { Xkey_2, EL_EM_KEY_2 },
5408 { Xkey_3, EL_EM_KEY_3 },
5409 { Xkey_4, EL_EM_KEY_4 },
5410 { Xkey_5, EL_EMC_KEY_5 },
5411 { Xkey_6, EL_EMC_KEY_6 },
5412 { Xkey_7, EL_EMC_KEY_7 },
5413 { Xkey_8, EL_EMC_KEY_8 },
5414 { Xwind_n, EL_BALLOON_SWITCH_UP },
5415 { Xwind_e, EL_BALLOON_SWITCH_RIGHT },
5416 { Xwind_s, EL_BALLOON_SWITCH_DOWN },
5417 { Xwind_w, EL_BALLOON_SWITCH_LEFT },
5418 { Xwind_nesw, EL_BALLOON_SWITCH_ANY },
5419 { Xwind_stop, EL_BALLOON_SWITCH_NONE },
5420 { Xexit, EL_EXIT_CLOSED },
5421 { Xexit_1, EL_EXIT_OPEN },
5422 { Xexit_2, EL_EXIT_OPEN },
5423 { Xexit_3, EL_EXIT_OPEN },
5424 { Xdynamite, EL_DYNAMITE },
5425 { Ydynamite_eat, EL_DYNAMITE },
5426 { Xdynamite_1, EL_DYNAMITE_ACTIVE },
5427 { Xdynamite_2, EL_DYNAMITE_ACTIVE },
5428 { Xdynamite_3, EL_DYNAMITE_ACTIVE },
5429 { Xdynamite_4, EL_DYNAMITE_ACTIVE },
5430 { Xbumper, EL_EMC_BUMPER },
5431 { XbumperB, EL_EMC_BUMPER },
5432 { Xwheel, EL_ROBOT_WHEEL },
5433 { XwheelB, EL_ROBOT_WHEEL },
5434 { Xswitch, EL_UNKNOWN },
5435 { XswitchB, EL_UNKNOWN },
5436 { Xsand, EL_QUICKSAND_EMPTY },
5437 { Xsand_stone, EL_QUICKSAND_FULL },
5438 { Xsand_stonein_1, EL_QUICKSAND_FULL },
5439 { Xsand_stonein_2, EL_QUICKSAND_FULL },
5440 { Xsand_stonein_3, EL_QUICKSAND_FULL },
5441 { Xsand_stonein_4, EL_QUICKSAND_FULL },
5442 { Xsand_stonesand_1, EL_QUICKSAND_FULL },
5443 { Xsand_stonesand_2, EL_QUICKSAND_FULL },
5444 { Xsand_stonesand_3, EL_QUICKSAND_FULL },
5445 { Xsand_stonesand_4, EL_QUICKSAND_FULL },
5446 { Xsand_stoneout_1, EL_QUICKSAND_FULL },
5447 { Xsand_stoneout_2, EL_QUICKSAND_FULL },
5448 { Xsand_sandstone_1, EL_QUICKSAND_FULL },
5449 { Xsand_sandstone_2, EL_QUICKSAND_FULL },
5450 { Xsand_sandstone_3, EL_QUICKSAND_FULL },
5451 { Xsand_sandstone_4, EL_QUICKSAND_FULL },
5452 { Xplant, EL_EMC_PLANT },
5453 { Yplant, EL_EMC_PLANT },
5454 { Xlenses, EL_EMC_LENSES },
5455 { Xmagnify, EL_EMC_MAGNIFIER },
5456 { Xdripper, EL_UNKNOWN },
5457 { XdripperB, EL_UNKNOWN },
5458 { Xfake_blank, EL_INVISIBLE_WALL },
5459 { Xfake_blankB, EL_INVISIBLE_WALL },
5460 { Xfake_grass, EL_INVISIBLE_SAND },
5461 { Xfake_grassB, EL_INVISIBLE_SAND },
5462 { Xfake_door_1, EL_EM_GATE_1_GRAY },
5463 { Xfake_door_2, EL_EM_GATE_2_GRAY },
5464 { Xfake_door_3, EL_EM_GATE_3_GRAY },
5465 { Xfake_door_4, EL_EM_GATE_4_GRAY },
5466 { Xfake_door_5, EL_EMC_GATE_5_GRAY },
5467 { Xfake_door_6, EL_EMC_GATE_6_GRAY },
5468 { Xfake_door_7, EL_EMC_GATE_7_GRAY },
5469 { Xfake_door_8, EL_EMC_GATE_8_GRAY },
5470 { Xsteel_1, EL_STEELWALL },
5471 { Xsteel_2, EL_UNKNOWN },
5472 { Xsteel_3, EL_EMC_STEELWALL_1 },
5473 { Xsteel_4, EL_UNKNOWN },
5474 { Xwall_1, EL_WALL },
5475 { Xwall_2, EL_UNKNOWN },
5476 { Xwall_3, EL_UNKNOWN },
5477 { Xwall_4, EL_UNKNOWN },
5478 { Xround_wall_1, EL_WALL_SLIPPERY },
5479 { Xround_wall_2, EL_UNKNOWN },
5480 { Xround_wall_3, EL_UNKNOWN },
5481 { Xround_wall_4, EL_UNKNOWN },
5482 { Xdecor_1, EL_UNKNOWN },
5483 { Xdecor_2, EL_EMC_WALL_6 },
5484 { Xdecor_3, EL_EMC_WALL_4 },
5485 { Xdecor_4, EL_EMC_WALL_5 },
5486 { Xdecor_5, EL_EMC_WALL_7 },
5487 { Xdecor_6, EL_EMC_WALL_8 },
5488 { Xdecor_7, EL_UNKNOWN },
5489 { Xdecor_8, EL_EMC_WALL_1 },
5490 { Xdecor_9, EL_EMC_WALL_2 },
5491 { Xdecor_10, EL_EMC_WALL_3 },
5492 { Xdecor_11, EL_UNKNOWN },
5493 { Xdecor_12, EL_UNKNOWN },
5494 { Xalpha_0, EL_CHAR('0') },
5495 { Xalpha_1, EL_CHAR('1') },
5496 { Xalpha_2, EL_CHAR('2') },
5497 { Xalpha_3, EL_CHAR('3') },
5498 { Xalpha_4, EL_CHAR('4') },
5499 { Xalpha_5, EL_CHAR('5') },
5500 { Xalpha_6, EL_CHAR('6') },
5501 { Xalpha_7, EL_CHAR('7') },
5502 { Xalpha_8, EL_CHAR('8') },
5503 { Xalpha_9, EL_CHAR('9') },
5504 { Xalpha_excla, EL_CHAR('!') },
5505 { Xalpha_quote, EL_CHAR('"') },
5506 { Xalpha_comma, EL_CHAR(',') },
5507 { Xalpha_minus, EL_CHAR('-') },
5508 { Xalpha_perio, EL_CHAR('.') },
5509 { Xalpha_colon, EL_CHAR(':') },
5510 { Xalpha_quest, EL_CHAR('?') },
5511 { Xalpha_a, EL_CHAR('A') },
5512 { Xalpha_b, EL_CHAR('B') },
5513 { Xalpha_c, EL_CHAR('C') },
5514 { Xalpha_d, EL_CHAR('D') },
5515 { Xalpha_e, EL_CHAR('E') },
5516 { Xalpha_f, EL_CHAR('F') },
5517 { Xalpha_g, EL_CHAR('G') },
5518 { Xalpha_h, EL_CHAR('H') },
5519 { Xalpha_i, EL_CHAR('I') },
5520 { Xalpha_j, EL_CHAR('J') },
5521 { Xalpha_k, EL_CHAR('K') },
5522 { Xalpha_l, EL_CHAR('L') },
5523 { Xalpha_m, EL_CHAR('M') },
5524 { Xalpha_n, EL_CHAR('N') },
5525 { Xalpha_o, EL_CHAR('O') },
5526 { Xalpha_p, EL_CHAR('P') },
5527 { Xalpha_q, EL_CHAR('Q') },
5528 { Xalpha_r, EL_CHAR('R') },
5529 { Xalpha_s, EL_CHAR('S') },
5530 { Xalpha_t, EL_CHAR('T') },
5531 { Xalpha_u, EL_CHAR('U') },
5532 { Xalpha_v, EL_CHAR('V') },
5533 { Xalpha_w, EL_CHAR('W') },
5534 { Xalpha_x, EL_CHAR('X') },
5535 { Xalpha_y, EL_CHAR('Y') },
5536 { Xalpha_z, EL_CHAR('Z') },
5537 { Xalpha_arrow_e, EL_CHAR('>') },
5538 { Xalpha_arrow_w, EL_CHAR('<') },
5539 { Xalpha_copyr, EL_CHAR('©') },
5541 { Zplayer, EL_PLAYER_1 },
5543 { ZBORDER, EL_EMC_LEVEL_BORDER },
5548 if (!mapping_initialized)
5552 /* return "EL_UNKNOWN" for all undefined elements in mapping array */
5553 for (i = 0; i < TILE_MAX; i++)
5554 mapping_EM_to_RND[i] = EL_UNKNOWN;
5556 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
5557 mapping_EM_to_RND[em_object_mapping_list[i].element_em] =
5558 em_object_mapping_list[i].element_rnd;
5560 mapping_initialized = TRUE;
5563 if (element_em >= 0 && element_em < TILE_MAX)
5564 return mapping_EM_to_RND[element_em];
5566 Error(ERR_WARN, "invalid EM level element %d", element_em);
5573 int get_next_element(int element)
5577 case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL;
5578 case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY;
5579 case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL;
5580 case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_ACTIVE;
5581 case EL_BD_MAGIC_WALL_FILLING: return EL_BD_MAGIC_WALL_FULL;
5582 case EL_BD_MAGIC_WALL_EMPTYING: return EL_BD_MAGIC_WALL_ACTIVE;
5583 case EL_AMOEBA_DROPPING: return EL_AMOEBA_WET;
5585 default: return element;
5590 int el_act_dir2img(int element, int action, int direction)
5592 element = GFX_ELEMENT(element);
5594 if (direction == MV_NO_MOVING)
5595 return element_info[element].graphic[action];
5597 direction = MV_DIR_BIT(direction);
5599 return element_info[element].direction_graphic[action][direction];
5602 int el_act_dir2img(int element, int action, int direction)
5604 element = GFX_ELEMENT(element);
5605 direction = MV_DIR_BIT(direction); /* default: MV_NO_MOVING => MV_DOWN */
5607 /* direction_graphic[][] == graphic[] for undefined direction graphics */
5608 return element_info[element].direction_graphic[action][direction];
5613 static int el_act_dir2crm(int element, int action, int direction)
5615 element = GFX_ELEMENT(element);
5617 if (direction == MV_NO_MOVING)
5618 return element_info[element].crumbled[action];
5620 direction = MV_DIR_BIT(direction);
5622 return element_info[element].direction_crumbled[action][direction];
5625 static int el_act_dir2crm(int element, int action, int direction)
5627 element = GFX_ELEMENT(element);
5628 direction = MV_DIR_BIT(direction); /* default: MV_NO_MOVING => MV_DOWN */
5630 /* direction_graphic[][] == graphic[] for undefined direction graphics */
5631 return element_info[element].direction_crumbled[action][direction];
5635 int el_act2img(int element, int action)
5637 element = GFX_ELEMENT(element);
5639 return element_info[element].graphic[action];
5642 int el_act2crm(int element, int action)
5644 element = GFX_ELEMENT(element);
5646 return element_info[element].crumbled[action];
5649 int el_dir2img(int element, int direction)
5651 element = GFX_ELEMENT(element);
5653 return el_act_dir2img(element, ACTION_DEFAULT, direction);
5656 int el2baseimg(int element)
5658 return element_info[element].graphic[ACTION_DEFAULT];
5661 int el2img(int element)
5663 element = GFX_ELEMENT(element);
5665 return element_info[element].graphic[ACTION_DEFAULT];
5668 int el2edimg(int element)
5670 element = GFX_ELEMENT(element);
5672 return element_info[element].special_graphic[GFX_SPECIAL_ARG_EDITOR];
5675 int el2preimg(int element)
5677 element = GFX_ELEMENT(element);
5679 return element_info[element].special_graphic[GFX_SPECIAL_ARG_PREVIEW];
5682 int getGameFrameDelay_EM(int native_em_game_frame_delay)
5684 int game_frame_delay_value;
5686 game_frame_delay_value =
5687 (tape.playing && tape.fast_forward ? FfwdFrameDelay :
5688 GameFrameDelay == GAME_FRAME_DELAY ? native_em_game_frame_delay :
5691 if (tape.playing && tape.warp_forward && !tape.pausing)
5692 game_frame_delay_value = 0;
5694 return game_frame_delay_value;
5697 unsigned int InitRND(long seed)
5699 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
5700 return InitEngineRND_EM(seed);
5702 return InitEngineRND(seed);
5705 #define DEBUG_EM_GFX 0
5707 void InitGraphicInfo_EM(void)
5709 struct Mapping_EM_to_RND_object object_mapping[TILE_MAX];
5710 struct Mapping_EM_to_RND_player player_mapping[2][SPR_MAX];
5714 if (graphic_info_em_object[0][0].bitmap == NULL)
5716 /* EM graphics not yet initialized in em_open_all() */
5722 /* always start with reliable default values */
5723 for (i = 0; i < TILE_MAX; i++)
5725 object_mapping[i].element_rnd = EL_UNKNOWN;
5726 object_mapping[i].is_backside = FALSE;
5727 object_mapping[i].action = ACTION_DEFAULT;
5728 object_mapping[i].direction = MV_NO_MOVING;
5731 /* always start with reliable default values */
5732 for (p = 0; p < 2; p++)
5734 for (i = 0; i < SPR_MAX; i++)
5736 player_mapping[p][i].element_rnd = EL_UNKNOWN;
5737 player_mapping[p][i].action = ACTION_DEFAULT;
5738 player_mapping[p][i].direction = MV_NO_MOVING;
5742 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
5744 int e = em_object_mapping_list[i].element_em;
5746 object_mapping[e].element_rnd = em_object_mapping_list[i].element_rnd;
5747 object_mapping[e].is_backside = em_object_mapping_list[i].is_backside;
5749 if (em_object_mapping_list[i].action != -1)
5750 object_mapping[e].action = em_object_mapping_list[i].action;
5752 if (em_object_mapping_list[i].direction != -1)
5753 object_mapping[e].direction = (1 << em_object_mapping_list[i].direction);
5756 for (i = 0; em_player_mapping_list[i].action_em != -1; i++)
5758 int a = em_player_mapping_list[i].action_em;
5759 int p = em_player_mapping_list[i].player_nr;
5761 player_mapping[p][a].element_rnd = em_player_mapping_list[i].element_rnd;
5763 if (em_player_mapping_list[i].action != -1)
5764 player_mapping[p][a].action = em_player_mapping_list[i].action;
5766 if (em_player_mapping_list[i].direction != -1)
5767 player_mapping[p][a].direction =
5768 (1 << em_player_mapping_list[i].direction);
5771 for (i = 0; i < TILE_MAX; i++)
5773 int element = object_mapping[i].element_rnd;
5774 int action = object_mapping[i].action;
5775 int direction = object_mapping[i].direction;
5776 boolean is_backside = object_mapping[i].is_backside;
5777 boolean action_removing = (action == ACTION_DIGGING ||
5778 action == ACTION_SNAPPING ||
5779 action == ACTION_COLLECTING);
5780 boolean action_exploding = ((action == ACTION_EXPLODING ||
5781 action == ACTION_SMASHED_BY_ROCK ||
5782 action == ACTION_SMASHED_BY_SPRING) &&
5783 element != EL_DIAMOND);
5784 boolean action_active = (action == ACTION_ACTIVE);
5785 boolean action_other = (action == ACTION_OTHER);
5787 for (j = 0; j < 8; j++)
5789 int effective_element = (j > 5 && i == Yacid_splash_eB ? EL_EMPTY :
5790 j > 5 && i == Yacid_splash_wB ? EL_EMPTY :
5792 i == Xdrip_stretch ? element :
5793 i == Xdrip_stretchB ? element :
5794 i == Ydrip_s1 ? element :
5795 i == Ydrip_s1B ? element :
5796 i == Xball_1B ? element :
5797 i == Xball_2 ? element :
5798 i == Xball_2B ? element :
5799 i == Yball_eat ? element :
5800 i == Ykey_1_eat ? element :
5801 i == Ykey_2_eat ? element :
5802 i == Ykey_3_eat ? element :
5803 i == Ykey_4_eat ? element :
5804 i == Ykey_5_eat ? element :
5805 i == Ykey_6_eat ? element :
5806 i == Ykey_7_eat ? element :
5807 i == Ykey_8_eat ? element :
5808 i == Ylenses_eat ? element :
5809 i == Ymagnify_eat ? element :
5810 i == Ygrass_eat ? element :
5811 i == Ydirt_eat ? element :
5812 i == Yspring_kill_e ? EL_SPRING :
5813 i == Yspring_kill_w ? EL_SPRING :
5814 i == Yemerald_stone ? EL_EMERALD :
5815 i == Ydiamond_stone ? EL_ROCK :
5816 i == Xsand_stonein_4 ? EL_EMPTY :
5817 i == Xsand_stoneout_2 ? EL_ROCK :
5818 is_backside ? EL_EMPTY :
5819 action_removing ? EL_EMPTY :
5821 int effective_action = (j < 7 ? action :
5822 i == Xdrip_stretch ? action :
5823 i == Xdrip_stretchB ? action :
5824 i == Ydrip_s1 ? action :
5825 i == Ydrip_s1B ? action :
5826 i == Xball_1B ? action :
5827 i == Xball_2 ? action :
5828 i == Xball_2B ? action :
5829 i == Yball_eat ? action :
5830 i == Ykey_1_eat ? action :
5831 i == Ykey_2_eat ? action :
5832 i == Ykey_3_eat ? action :
5833 i == Ykey_4_eat ? action :
5834 i == Ykey_5_eat ? action :
5835 i == Ykey_6_eat ? action :
5836 i == Ykey_7_eat ? action :
5837 i == Ykey_8_eat ? action :
5838 i == Ylenses_eat ? action :
5839 i == Ymagnify_eat ? action :
5840 i == Ygrass_eat ? action :
5841 i == Ydirt_eat ? action :
5842 i == Xsand_stonein_1 ? action :
5843 i == Xsand_stonein_2 ? action :
5844 i == Xsand_stonein_3 ? action :
5845 i == Xsand_stonein_4 ? action :
5846 i == Xsand_stoneout_1 ? action :
5847 i == Xsand_stoneout_2 ? action :
5848 i == Xboom_android ? ACTION_EXPLODING :
5849 action_exploding ? ACTION_EXPLODING :
5850 action_active ? action :
5851 action_other ? action :
5853 int graphic = (el_act_dir2img(effective_element, effective_action,
5855 int crumbled = (el_act_dir2crm(effective_element, effective_action,
5857 int base_graphic = el_act2img(effective_element, ACTION_DEFAULT);
5858 int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT);
5859 boolean has_crumbled_graphics = (base_crumbled != base_graphic);
5860 struct GraphicInfo *g = &graphic_info[graphic];
5861 struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
5864 /* ensure to get symmetric 3-frame, 2-delay animations as used in EM */
5865 boolean special_animation = (action != ACTION_DEFAULT &&
5866 g->anim_frames == 3 &&
5867 g->anim_delay == 2 &&
5868 g->anim_mode & ANIM_LINEAR);
5869 int sync_frame = (i == Xdrip_stretch ? 7 :
5870 i == Xdrip_stretchB ? 7 :
5871 i == Ydrip_s2 ? j + 8 :
5872 i == Ydrip_s2B ? j + 8 :
5881 i == Xfake_acid_1 ? 0 :
5882 i == Xfake_acid_2 ? 10 :
5883 i == Xfake_acid_3 ? 20 :
5884 i == Xfake_acid_4 ? 30 :
5885 i == Xfake_acid_5 ? 40 :
5886 i == Xfake_acid_6 ? 50 :
5887 i == Xfake_acid_7 ? 60 :
5888 i == Xfake_acid_8 ? 70 :
5890 i == Xball_2B ? j + 8 :
5891 i == Yball_eat ? j + 1 :
5892 i == Ykey_1_eat ? j + 1 :
5893 i == Ykey_2_eat ? j + 1 :
5894 i == Ykey_3_eat ? j + 1 :
5895 i == Ykey_4_eat ? j + 1 :
5896 i == Ykey_5_eat ? j + 1 :
5897 i == Ykey_6_eat ? j + 1 :
5898 i == Ykey_7_eat ? j + 1 :
5899 i == Ykey_8_eat ? j + 1 :
5900 i == Ylenses_eat ? j + 1 :
5901 i == Ymagnify_eat ? j + 1 :
5902 i == Ygrass_eat ? j + 1 :
5903 i == Ydirt_eat ? j + 1 :
5904 i == Xamoeba_1 ? 0 :
5905 i == Xamoeba_2 ? 1 :
5906 i == Xamoeba_3 ? 2 :
5907 i == Xamoeba_4 ? 3 :
5908 i == Xamoeba_5 ? 0 :
5909 i == Xamoeba_6 ? 1 :
5910 i == Xamoeba_7 ? 2 :
5911 i == Xamoeba_8 ? 3 :
5912 i == Xexit_2 ? j + 8 :
5913 i == Xexit_3 ? j + 16 :
5914 i == Xdynamite_1 ? 0 :
5915 i == Xdynamite_2 ? 20 :
5916 i == Xdynamite_3 ? 40 :
5917 i == Xdynamite_4 ? 60 :
5918 i == Xsand_stonein_1 ? j + 1 :
5919 i == Xsand_stonein_2 ? j + 9 :
5920 i == Xsand_stonein_3 ? j + 17 :
5921 i == Xsand_stonein_4 ? j + 25 :
5922 i == Xsand_stoneout_1 && j == 0 ? 0 :
5923 i == Xsand_stoneout_1 && j == 1 ? 0 :
5924 i == Xsand_stoneout_1 && j == 2 ? 1 :
5925 i == Xsand_stoneout_1 && j == 3 ? 2 :
5926 i == Xsand_stoneout_1 && j == 4 ? 2 :
5927 i == Xsand_stoneout_1 && j == 5 ? 3 :
5928 i == Xsand_stoneout_1 && j == 6 ? 4 :
5929 i == Xsand_stoneout_1 && j == 7 ? 4 :
5930 i == Xsand_stoneout_2 && j == 0 ? 5 :
5931 i == Xsand_stoneout_2 && j == 1 ? 6 :
5932 i == Xsand_stoneout_2 && j == 2 ? 7 :
5933 i == Xsand_stoneout_2 && j == 3 ? 8 :
5934 i == Xsand_stoneout_2 && j == 4 ? 9 :
5935 i == Xsand_stoneout_2 && j == 5 ? 11 :
5936 i == Xsand_stoneout_2 && j == 6 ? 13 :
5937 i == Xsand_stoneout_2 && j == 7 ? 15 :
5938 i == Xboom_bug && j == 1 ? 2 :
5939 i == Xboom_bug && j == 2 ? 2 :
5940 i == Xboom_bug && j == 3 ? 4 :
5941 i == Xboom_bug && j == 4 ? 4 :
5942 i == Xboom_bug && j == 5 ? 2 :
5943 i == Xboom_bug && j == 6 ? 2 :
5944 i == Xboom_bug && j == 7 ? 0 :
5945 i == Xboom_bomb && j == 1 ? 2 :
5946 i == Xboom_bomb && j == 2 ? 2 :
5947 i == Xboom_bomb && j == 3 ? 4 :
5948 i == Xboom_bomb && j == 4 ? 4 :
5949 i == Xboom_bomb && j == 5 ? 2 :
5950 i == Xboom_bomb && j == 6 ? 2 :
5951 i == Xboom_bomb && j == 7 ? 0 :
5952 i == Xboom_android && j == 7 ? 6 :
5953 i == Xboom_1 && j == 1 ? 2 :
5954 i == Xboom_1 && j == 2 ? 2 :
5955 i == Xboom_1 && j == 3 ? 4 :
5956 i == Xboom_1 && j == 4 ? 4 :
5957 i == Xboom_1 && j == 5 ? 6 :
5958 i == Xboom_1 && j == 6 ? 6 :
5959 i == Xboom_1 && j == 7 ? 8 :
5960 i == Xboom_2 && j == 0 ? 8 :
5961 i == Xboom_2 && j == 1 ? 8 :
5962 i == Xboom_2 && j == 2 ? 10 :
5963 i == Xboom_2 && j == 3 ? 10 :
5964 i == Xboom_2 && j == 4 ? 10 :
5965 i == Xboom_2 && j == 5 ? 12 :
5966 i == Xboom_2 && j == 6 ? 12 :
5967 i == Xboom_2 && j == 7 ? 12 :
5968 special_animation && j == 4 ? 3 :
5969 effective_action != action ? 0 :
5973 Bitmap *debug_bitmap = g_em->bitmap;
5974 int debug_src_x = g_em->src_x;
5975 int debug_src_y = g_em->src_y;
5978 int frame = getAnimationFrame(g->anim_frames,
5981 g->anim_start_frame,
5984 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y,
5985 g->double_movement && is_backside);
5988 g_em->bitmap = src_bitmap;
5989 g_em->src_x = src_x;
5990 g_em->src_y = src_y;
5991 g_em->src_offset_x = 0;
5992 g_em->src_offset_y = 0;
5993 g_em->dst_offset_x = 0;
5994 g_em->dst_offset_y = 0;
5995 g_em->width = TILEX;
5996 g_em->height = TILEY;
5998 g_em->crumbled_bitmap = NULL;
5999 g_em->crumbled_src_x = 0;
6000 g_em->crumbled_src_y = 0;
6001 g_em->crumbled_border_size = 0;
6003 g_em->has_crumbled_graphics = FALSE;
6004 g_em->preserve_background = FALSE;
6008 if (effective_element == EL_EMC_GRASS &&
6009 effective_action == ACTION_DIGGING)
6010 printf("::: %d\n", crumbled);
6014 if (has_crumbled_graphics && crumbled == IMG_EMPTY_SPACE)
6015 printf("::: empty crumbled: %d [%s], %d, %d\n",
6016 effective_element, element_info[effective_element].token_name,
6017 effective_action, direction);
6020 /* if element can be crumbled, but certain action graphics are just empty
6021 space (like snapping sand with the original R'n'D graphics), do not
6022 treat these empty space graphics as crumbled graphics in EMC engine */
6023 if (has_crumbled_graphics && crumbled != IMG_EMPTY_SPACE)
6025 getGraphicSource(crumbled, frame, &src_bitmap, &src_x, &src_y);
6027 g_em->has_crumbled_graphics = TRUE;
6028 g_em->crumbled_bitmap = src_bitmap;
6029 g_em->crumbled_src_x = src_x;
6030 g_em->crumbled_src_y = src_y;
6031 g_em->crumbled_border_size = graphic_info[crumbled].border_size;
6035 if (!g->double_movement && (effective_action == ACTION_FALLING ||
6036 effective_action == ACTION_MOVING ||
6037 effective_action == ACTION_PUSHING))
6040 (effective_action == ACTION_FALLING ? MV_DOWN : direction);
6041 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? 1 : 0);
6042 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? 1 : 0);
6043 int num_steps = (i == Ydrip_s1 ||
6046 i == Ydrip_s2B ? 16 : 8);
6047 int cx = ABS(dx) * (TILEX / num_steps);
6048 int cy = ABS(dy) * (TILEY / num_steps);
6049 int step_frame = (i == Ydrip_s2 ||
6050 i == Ydrip_s2B ? j + 8 : j) + 1;
6051 int step = (is_backside ? step_frame : num_steps - step_frame);
6053 if (is_backside) /* tile where movement starts */
6055 if (dx < 0 || dy < 0)
6057 g_em->src_offset_x = cx * step;
6058 g_em->src_offset_y = cy * step;
6062 g_em->dst_offset_x = cx * step;
6063 g_em->dst_offset_y = cy * step;
6066 else /* tile where movement ends */
6068 if (dx < 0 || dy < 0)
6070 g_em->dst_offset_x = cx * step;
6071 g_em->dst_offset_y = cy * step;
6075 g_em->src_offset_x = cx * step;
6076 g_em->src_offset_y = cy * step;
6080 g_em->width = TILEX - cx * step;
6081 g_em->height = TILEY - cy * step;
6085 if (effective_action == ACTION_SMASHED_BY_ROCK &&
6086 element_info[effective_element].graphic[effective_action] ==
6087 element_info[effective_element].graphic[ACTION_DEFAULT])
6089 int move_dir = MV_DOWN;
6090 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? 1 : 0);
6091 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? 1 : 0);
6093 int cx = ABS(dx) * (TILEX / num_steps);
6094 int cy = ABS(dy) * (TILEY / num_steps);
6095 int step_frame = j + 1;
6096 int step = (is_backside ? step_frame : num_steps - step_frame);
6098 graphic = (el_act_dir2img(EL_ROCK, ACTION_FALLING, MV_DOWN));
6099 g = &graphic_info[graphic];
6101 frame = getAnimationFrame(g->anim_frames,
6104 g->anim_start_frame,
6106 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y,
6107 g->double_movement && is_backside);
6109 g_em->bitmap = src_bitmap;
6110 g_em->src_x = src_x;
6111 g_em->src_y = src_y;
6112 g_em->src_offset_x = 0;
6113 g_em->src_offset_y = 0;
6114 g_em->dst_offset_x = 0;
6115 g_em->dst_offset_y = 0;
6117 if (is_backside) /* tile where movement starts */
6119 if (dx < 0 || dy < 0)
6121 g_em->src_offset_x = cx * step;
6122 g_em->src_offset_y = cy * step;
6126 g_em->dst_offset_x = cx * step;
6127 g_em->dst_offset_y = cy * step;
6130 else /* tile where movement ends */
6132 if (dx < 0 || dy < 0)
6134 g_em->dst_offset_x = cx * step;
6135 g_em->dst_offset_y = cy * step;
6139 g_em->src_offset_x = cx * step;
6140 g_em->src_offset_y = cy * step;
6144 g_em->width = TILEX - cx * step;
6145 g_em->height = TILEY - cy * step;
6148 printf("::: -> '%s'\n", element_info[effective_element].token_name);
6155 /* create unique graphic identifier to decide if tile must be redrawn */
6156 /* bit 31 - 16 (16 bit): EM style element
6157 bit 15 - 12 ( 4 bit): EM style frame
6158 bit 11 - 6 ( 6 bit): graphic width
6159 bit 5 - 0 ( 6 bit): graphic height */
6160 g_em->unique_identifier =
6161 (i << 16) | (j << 12) | (g_em->width << 6) | g_em->height;
6164 if (g_em->bitmap != debug_bitmap ||
6165 g_em->src_x != debug_src_x ||
6166 g_em->src_y != debug_src_y ||
6167 g_em->src_offset_x != 0 ||
6168 g_em->src_offset_y != 0 ||
6169 g_em->dst_offset_x != 0 ||
6170 g_em->dst_offset_y != 0 ||
6171 g_em->width != TILEX ||
6172 g_em->height != TILEY)
6174 static int last_i = -1;
6182 printf("::: EMC GFX ERROR for element %d -> %d ('%s', '%s', %d)",
6183 i, element, element_info[element].token_name,
6184 element_action_info[effective_action].suffix, direction);
6186 if (element != effective_element)
6187 printf(" [%d ('%s')]",
6189 element_info[effective_element].token_name);
6193 if (g_em->bitmap != debug_bitmap)
6194 printf(" %d (%d): different bitmap! (0x%08x != 0x%08x)\n",
6195 j, is_backside, (int)(g_em->bitmap), (int)(debug_bitmap));
6197 if (g_em->src_x != debug_src_x ||
6198 g_em->src_y != debug_src_y)
6199 printf(" frame %d (%c): %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
6200 j, (is_backside ? 'B' : 'F'),
6201 g_em->src_x, g_em->src_y,
6202 g_em->src_x / 32, g_em->src_y / 32,
6203 debug_src_x, debug_src_y,
6204 debug_src_x / 32, debug_src_y / 32);
6206 if (g_em->src_offset_x != 0 ||
6207 g_em->src_offset_y != 0 ||
6208 g_em->dst_offset_x != 0 ||
6209 g_em->dst_offset_y != 0)
6210 printf(" %d (%d): offsets %d,%d and %d,%d should be all 0\n",
6212 g_em->src_offset_x, g_em->src_offset_y,
6213 g_em->dst_offset_x, g_em->dst_offset_y);
6215 if (g_em->width != TILEX ||
6216 g_em->height != TILEY)
6217 printf(" %d (%d): size %d,%d should be %d,%d\n",
6219 g_em->width, g_em->height, TILEX, TILEY);
6227 for (i = 0; i < TILE_MAX; i++)
6229 for (j = 0; j < 8; j++)
6231 int element = object_mapping[i].element_rnd;
6232 int action = object_mapping[i].action;
6234 if (action == ACTION_SMASHED_BY_ROCK &&
6235 element_info[element].graphic[action] ==
6236 element_info[element].graphic[ACTION_DEFAULT])
6238 /* no separate animation for "smashed by rock" -- use rock instead */
6239 struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
6240 struct GraphicInfo_EM *g_xx = &graphic_info_em_object[Ystone_s][7 - j];
6242 g_em->bitmap = g_xx->bitmap;
6243 g_em->src_x = g_xx->src_x;
6244 g_em->src_y = g_xx->src_y;
6245 g_em->src_offset_x = g_xx->src_offset_x;
6246 g_em->src_offset_y = g_xx->src_offset_y;
6247 g_em->dst_offset_x = g_xx->dst_offset_x;
6248 g_em->dst_offset_y = g_xx->dst_offset_y;
6249 g_em->width = g_xx->width;
6250 g_em->height = g_xx->height;
6252 g_em->preserve_background = TRUE;
6258 for (p = 0; p < 2; p++)
6260 for (i = 0; i < SPR_MAX; i++)
6262 int element = player_mapping[p][i].element_rnd;
6263 int action = player_mapping[p][i].action;
6264 int direction = player_mapping[p][i].direction;
6266 for (j = 0; j < 8; j++)
6268 int effective_element = element;
6269 int effective_action = action;
6270 int graphic = (direction == MV_NO_MOVING ?
6271 el_act2img(effective_element, effective_action) :
6272 el_act_dir2img(effective_element, effective_action,
6274 struct GraphicInfo *g = &graphic_info[graphic];
6275 struct GraphicInfo_EM *g_em = &graphic_info_em_player[p][i][7 - j];
6281 Bitmap *debug_bitmap = g_em->bitmap;
6282 int debug_src_x = g_em->src_x;
6283 int debug_src_y = g_em->src_y;
6286 int frame = getAnimationFrame(g->anim_frames,
6289 g->anim_start_frame,
6292 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x,&src_y, FALSE);
6295 g_em->bitmap = src_bitmap;
6296 g_em->src_x = src_x;
6297 g_em->src_y = src_y;
6298 g_em->src_offset_x = 0;
6299 g_em->src_offset_y = 0;
6300 g_em->dst_offset_x = 0;
6301 g_em->dst_offset_y = 0;
6302 g_em->width = TILEX;
6303 g_em->height = TILEY;
6307 if (g_em->bitmap != debug_bitmap ||
6308 g_em->src_x != debug_src_x ||
6309 g_em->src_y != debug_src_y)
6311 static int last_i = -1;
6319 printf("::: EMC GFX ERROR for p/a %d/%d -> %d ('%s', '%s', %d)",
6320 p, i, element, element_info[element].token_name,
6321 element_action_info[effective_action].suffix, direction);
6323 if (element != effective_element)
6324 printf(" [%d ('%s')]",
6326 element_info[effective_element].token_name);
6330 if (g_em->bitmap != debug_bitmap)
6331 printf(" %d: different bitmap! (0x%08x != 0x%08x)\n",
6332 j, (int)(g_em->bitmap), (int)(debug_bitmap));
6334 if (g_em->src_x != debug_src_x ||
6335 g_em->src_y != debug_src_y)
6336 printf(" frame %d: %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
6338 g_em->src_x, g_em->src_y,
6339 g_em->src_x / 32, g_em->src_y / 32,
6340 debug_src_x, debug_src_y,
6341 debug_src_x / 32, debug_src_y / 32);