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, MICROLEV_XSIZE, MICROLEV_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_CREATED_BY 2
1544 #define MICROLABEL_LEVEL_AUTHOR 3
1545 #define MICROLABEL_IMPORTED_FROM 4
1546 #define MICROLABEL_LEVEL_IMPORT_INFO 5
1548 static void DrawMicroLevelLabelExt(int mode)
1550 char label_text[MAX_OUTPUT_LINESIZE + 1];
1551 int max_len_label_text;
1552 int font_nr = FONT_TEXT_2;
1554 if (mode == MICROLABEL_CREATED_BY || mode == MICROLABEL_IMPORTED_FROM)
1555 font_nr = FONT_TEXT_3;
1557 max_len_label_text = SXSIZE / getFontWidth(font_nr);
1559 DrawBackground(SX, MICROLABEL_YPOS, SXSIZE, getFontHeight(font_nr));
1561 strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
1562 mode == MICROLABEL_CREATED_BY ? "created by" :
1563 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
1564 mode == MICROLABEL_IMPORTED_FROM ? "imported from" :
1565 mode == MICROLABEL_LEVEL_IMPORT_INFO ?
1566 leveldir_current->imported_from : ""),
1567 max_len_label_text);
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 = MICROLABEL_YPOS;
1575 DrawText(lxpos, lypos, label_text, font_nr);
1578 redraw_mask |= REDRAW_MICROLEVEL;
1581 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1583 static unsigned long scroll_delay = 0;
1584 static unsigned long label_delay = 0;
1585 static int from_x, from_y, scroll_direction;
1586 static int label_state, label_counter;
1587 int last_game_status = game_status; /* save current game status */
1589 /* force PREVIEW font on preview level */
1590 game_status = GAME_MODE_PSEUDO_PREVIEW;
1594 from_x = from_y = 0;
1595 scroll_direction = MV_RIGHT;
1599 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1600 DrawMicroLevelLabelExt(label_state);
1602 /* initialize delay counters */
1603 DelayReached(&scroll_delay, 0);
1604 DelayReached(&label_delay, 0);
1606 if (leveldir_current->name)
1608 int text_width = getTextWidth(leveldir_current->name, FONT_TEXT_1);
1609 int lxpos = SX + (SXSIZE - text_width) / 2;
1610 int lypos = SY + 352;
1612 DrawText(lxpos, lypos, leveldir_current->name, FONT_TEXT_1);
1615 game_status = last_game_status; /* restore current game status */
1620 /* scroll micro level, if needed */
1621 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1622 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1624 switch (scroll_direction)
1630 scroll_direction = MV_UP;
1634 if (from_x < lev_fieldx - STD_LEV_FIELDX)
1637 scroll_direction = MV_DOWN;
1644 scroll_direction = MV_RIGHT;
1648 if (from_y < lev_fieldy - STD_LEV_FIELDY)
1651 scroll_direction = MV_LEFT;
1658 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1661 /* redraw micro level label, if needed */
1662 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1663 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1664 strcmp(level.author, leveldir_current->name) != 0 &&
1665 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1667 int max_label_counter = 23;
1669 if (leveldir_current->imported_from != NULL)
1670 max_label_counter += 14;
1672 label_counter = (label_counter + 1) % max_label_counter;
1673 label_state = (label_counter >= 0 && label_counter <= 7 ?
1674 MICROLABEL_LEVEL_NAME :
1675 label_counter >= 9 && label_counter <= 12 ?
1676 MICROLABEL_CREATED_BY :
1677 label_counter >= 14 && label_counter <= 21 ?
1678 MICROLABEL_LEVEL_AUTHOR :
1679 label_counter >= 23 && label_counter <= 26 ?
1680 MICROLABEL_IMPORTED_FROM :
1681 label_counter >= 28 && label_counter <= 35 ?
1682 MICROLABEL_LEVEL_IMPORT_INFO : MICROLABEL_EMPTY);
1683 DrawMicroLevelLabelExt(label_state);
1686 game_status = last_game_status; /* restore current game status */
1689 inline void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
1690 int graphic, int sync_frame, int mask_mode)
1692 int frame = getGraphicAnimationFrame(graphic, sync_frame);
1694 if (mask_mode == USE_MASKING)
1695 DrawGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
1697 DrawGraphicExt(dst_bitmap, x, y, graphic, frame);
1700 inline void DrawGraphicAnimation(int x, int y, int graphic)
1702 int lx = LEVELX(x), ly = LEVELY(y);
1704 if (!IN_SCR_FIELD(x, y))
1707 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
1708 graphic, GfxFrame[lx][ly], NO_MASKING);
1709 MarkTileDirty(x, y);
1712 void DrawLevelGraphicAnimation(int x, int y, int graphic)
1714 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
1717 void DrawLevelElementAnimation(int x, int y, int element)
1720 int graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
1722 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
1724 DrawGraphicAnimation(SCREENX(x), SCREENY(y), el2img(element));
1728 inline void DrawLevelGraphicAnimationIfNeeded(int x, int y, int graphic)
1730 int sx = SCREENX(x), sy = SCREENY(y);
1732 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
1735 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
1738 DrawGraphicAnimation(sx, sy, graphic);
1740 if (GFX_CRUMBLED(Feld[x][y]))
1741 DrawLevelFieldCrumbledSand(x, y);
1744 void DrawLevelElementAnimationIfNeeded(int x, int y, int element)
1746 int sx = SCREENX(x), sy = SCREENY(y);
1749 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
1752 graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
1754 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
1757 DrawGraphicAnimation(sx, sy, graphic);
1759 if (GFX_CRUMBLED(element))
1760 DrawLevelFieldCrumbledSand(x, y);
1763 static int getPlayerGraphic(struct PlayerInfo *player, int move_dir)
1765 if (player->use_murphy_graphic)
1767 /* this works only because currently only one player can be "murphy" ... */
1768 static int last_horizontal_dir = MV_LEFT;
1769 int graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, move_dir);
1771 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
1772 last_horizontal_dir = move_dir;
1774 if (graphic == IMG_SP_MURPHY) /* undefined => use special graphic */
1776 int direction = (player->is_snapping ? move_dir : last_horizontal_dir);
1778 graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, direction);
1784 return el_act_dir2img(player->element_nr, player->GfxAction, move_dir);
1787 static boolean equalGraphics(int graphic1, int graphic2)
1789 struct GraphicInfo *g1 = &graphic_info[graphic1];
1790 struct GraphicInfo *g2 = &graphic_info[graphic2];
1792 return (g1->bitmap == g2->bitmap &&
1793 g1->src_x == g2->src_x &&
1794 g1->src_y == g2->src_y &&
1795 g1->anim_frames == g2->anim_frames &&
1796 g1->anim_delay == g2->anim_delay &&
1797 g1->anim_mode == g2->anim_mode);
1800 void DrawAllPlayers()
1804 for (i = 0; i < MAX_PLAYERS; i++)
1805 if (stored_player[i].active)
1806 DrawPlayer(&stored_player[i]);
1809 void DrawPlayerField(int x, int y)
1811 if (!IS_PLAYER(x, y))
1814 DrawPlayer(PLAYERINFO(x, y));
1817 void DrawPlayer(struct PlayerInfo *player)
1819 int jx = player->jx;
1820 int jy = player->jy;
1821 int move_dir = player->MovDir;
1823 int last_jx = player->last_jx;
1824 int last_jy = player->last_jy;
1825 int next_jx = jx + (jx - last_jx);
1826 int next_jy = jy + (jy - last_jy);
1827 boolean player_is_moving = (last_jx != jx || last_jy != jy ? TRUE : FALSE);
1829 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? +1 : 0);
1830 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? +1 : 0);
1831 int last_jx = (player->is_moving ? jx - dx : jx);
1832 int last_jy = (player->is_moving ? jy - dy : jy);
1833 int next_jx = jx + dx;
1834 int next_jy = jy + dy;
1835 boolean player_is_moving = (player->MovPos ? TRUE : FALSE);
1837 int sx = SCREENX(jx), sy = SCREENY(jy);
1838 int sxx = 0, syy = 0;
1839 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
1841 int action = ACTION_DEFAULT;
1842 int last_player_graphic = getPlayerGraphic(player, move_dir);
1843 int last_player_frame = player->Frame;
1846 if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
1850 if (!IN_LEV_FIELD(jx, jy))
1852 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
1853 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
1854 printf("DrawPlayerField(): This should never happen!\n");
1859 if (element == EL_EXPLOSION)
1862 action = (player->is_pushing ? ACTION_PUSHING :
1863 player->is_digging ? ACTION_DIGGING :
1864 player->is_collecting ? ACTION_COLLECTING :
1865 player->is_moving ? ACTION_MOVING :
1866 player->is_snapping ? ACTION_SNAPPING :
1867 player->is_dropping ? ACTION_DROPPING :
1868 player->is_waiting ? player->action_waiting : ACTION_DEFAULT);
1870 InitPlayerGfxAnimation(player, action, move_dir);
1872 /* ----------------------------------------------------------------------- */
1873 /* draw things in the field the player is leaving, if needed */
1874 /* ----------------------------------------------------------------------- */
1877 if (player->is_moving)
1879 if (player_is_moving)
1882 if (Back[last_jx][last_jy] && IS_DRAWABLE(last_element))
1884 DrawLevelElement(last_jx, last_jy, Back[last_jx][last_jy]);
1886 if (last_element == EL_DYNAMITE_ACTIVE ||
1887 last_element == EL_SP_DISK_RED_ACTIVE)
1888 DrawDynamite(last_jx, last_jy);
1890 DrawLevelFieldThruMask(last_jx, last_jy);
1892 else if (last_element == EL_DYNAMITE_ACTIVE ||
1893 last_element == EL_SP_DISK_RED_ACTIVE)
1894 DrawDynamite(last_jx, last_jy);
1896 DrawLevelField(last_jx, last_jy);
1898 if (player->is_pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
1899 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
1902 if (!IN_SCR_FIELD(sx, sy))
1905 if (setup.direct_draw)
1906 SetDrawtoField(DRAW_BUFFERED);
1908 /* ----------------------------------------------------------------------- */
1909 /* draw things behind the player, if needed */
1910 /* ----------------------------------------------------------------------- */
1913 DrawLevelElement(jx, jy, Back[jx][jy]);
1914 else if (IS_ACTIVE_BOMB(element))
1915 DrawLevelElement(jx, jy, EL_EMPTY);
1918 if (player_is_moving && GfxElement[jx][jy] != EL_UNDEFINED)
1920 if (GFX_CRUMBLED(GfxElement[jx][jy]))
1921 DrawLevelFieldCrumbledSandDigging(jx, jy, move_dir, player->StepFrame);
1924 int old_element = GfxElement[jx][jy];
1925 int old_graphic = el_act_dir2img(old_element, action, move_dir);
1926 int frame = getGraphicAnimationFrame(old_graphic, player->StepFrame);
1928 DrawGraphic(sx, sy, old_graphic, frame);
1933 GfxElement[jx][jy] = EL_UNDEFINED;
1935 DrawLevelField(jx, jy);
1939 /* ----------------------------------------------------------------------- */
1940 /* draw player himself */
1941 /* ----------------------------------------------------------------------- */
1945 graphic = getPlayerGraphic(player, move_dir);
1947 /* in the case of changed player action or direction, prevent the current
1948 animation frame from being restarted for identical animations */
1949 if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic))
1950 player->Frame = last_player_frame;
1954 if (player->use_murphy_graphic)
1956 static int last_horizontal_dir = MV_LEFT;
1958 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
1959 last_horizontal_dir = move_dir;
1961 graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, move_dir);
1963 if (graphic == IMG_SP_MURPHY) /* undefined => use special graphic */
1965 int direction = (player->is_snapping ? move_dir : last_horizontal_dir);
1967 graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, direction);
1971 graphic = el_act_dir2img(player->element_nr, player->GfxAction, move_dir);
1975 frame = getGraphicAnimationFrame(graphic, player->Frame);
1979 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
1980 sxx = player->GfxPos;
1982 syy = player->GfxPos;
1985 if (!setup.soft_scrolling && ScreenMovPos)
1988 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
1990 if (SHIELD_ON(player))
1992 int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
1993 IMG_SHIELD_NORMAL_ACTIVE);
1994 int frame = getGraphicAnimationFrame(graphic, -1);
1996 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
1999 /* ----------------------------------------------------------------------- */
2000 /* draw things the player is pushing, if needed */
2001 /* ----------------------------------------------------------------------- */
2004 printf("::: %d, %d [%d, %d] [%d]\n",
2005 player->is_pushing, player_is_moving, player->GfxAction,
2006 player->is_moving, player_is_moving);
2010 if (player->is_pushing && player->is_moving)
2012 if (player->is_pushing && player_is_moving)
2016 int px = SCREENX(jx), py = SCREENY(jy);
2017 int pxx = (TILEX - ABS(sxx)) * dx;
2018 int pyy = (TILEY - ABS(syy)) * dy;
2020 int px = SCREENX(next_jx), py = SCREENY(next_jy);
2029 if (!IS_MOVING(jx, jy)) /* push movement already finished */
2030 element = Feld[next_jx][next_jy];
2032 graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
2033 frame = getGraphicAnimationFrame(graphic, player->StepFrame);
2035 /* draw background element under pushed element (like the Sokoban field) */
2036 if (Back[next_jx][next_jy])
2037 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
2039 /* masked drawing is needed for EMC style (double) movement graphics */
2040 DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame, NO_CUTTING);
2043 if (Back[next_jx][next_jy])
2044 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
2046 if ((pxx || pyy) && element == EL_SOKOBAN_OBJECT)
2047 DrawGraphicShiftedThruMask(px, py, pxx, pyy, IMG_SOKOBAN_OBJECT, 0,
2051 int element = MovingOrBlocked2Element(next_jx, next_jy);
2052 int graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
2054 int frame = getGraphicAnimationFrame(graphic, player->StepFrame);
2056 int frame = getGraphicAnimationFrame(graphic, player->Frame);
2060 /* masked drawing is needed for EMC style (double) movement graphics */
2061 DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame,
2064 DrawGraphicShifted(px, py, pxx, pyy, graphic, frame,
2065 NO_CUTTING, NO_MASKING);
2071 /* ----------------------------------------------------------------------- */
2072 /* draw things in front of player (active dynamite or dynabombs) */
2073 /* ----------------------------------------------------------------------- */
2075 if (IS_ACTIVE_BOMB(element))
2077 graphic = el2img(element);
2078 frame = getGraphicAnimationFrame(graphic, GfxFrame[jx][jy]);
2080 if (game.emulation == EMU_SUPAPLEX)
2081 DrawGraphic(sx, sy, IMG_SP_DISK_RED, frame);
2083 DrawGraphicThruMask(sx, sy, graphic, frame);
2086 if (player_is_moving && last_element == EL_EXPLOSION)
2088 int graphic = el_act2img(GfxElement[last_jx][last_jy], ACTION_EXPLODING);
2089 int delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2);
2090 int phase = ExplodePhase[last_jx][last_jy] - 1;
2091 int frame = getGraphicAnimationFrame(graphic, phase - delay);
2094 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy), graphic, frame);
2097 /* ----------------------------------------------------------------------- */
2098 /* draw elements the player is just walking/passing through/under */
2099 /* ----------------------------------------------------------------------- */
2101 if (player_is_moving)
2103 /* handle the field the player is leaving ... */
2104 if (IS_ACCESSIBLE_INSIDE(last_element))
2105 DrawLevelField(last_jx, last_jy);
2106 else if (IS_ACCESSIBLE_UNDER(last_element))
2107 DrawLevelFieldThruMask(last_jx, last_jy);
2111 /* do not redraw accessible elements if the player is just pushing them */
2112 if (!player_is_moving || !player->is_pushing)
2114 /* ... and the field the player is entering */
2115 if (IS_ACCESSIBLE_INSIDE(element))
2116 DrawLevelField(jx, jy);
2117 else if (IS_ACCESSIBLE_UNDER(element))
2118 DrawLevelFieldThruMask(jx, jy);
2124 /* !!! I have forgotton what this should be good for !!! */
2125 /* !!! causes player being visible when pushing from within tubes !!! */
2126 if (!player->is_pushing)
2129 /* ... and the field the player is entering */
2130 if (IS_ACCESSIBLE_INSIDE(element))
2131 DrawLevelField(jx, jy);
2132 else if (IS_ACCESSIBLE_UNDER(element))
2133 DrawLevelFieldThruMask(jx, jy);
2137 if (setup.direct_draw)
2139 int dst_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
2140 int dst_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
2141 int x_size = TILEX * (1 + ABS(jx - last_jx));
2142 int y_size = TILEY * (1 + ABS(jy - last_jy));
2144 BlitBitmap(drawto_field, window,
2145 dst_x, dst_y, x_size, y_size, dst_x, dst_y);
2146 SetDrawtoField(DRAW_DIRECT);
2149 MarkTileDirty(sx, sy);
2152 /* ------------------------------------------------------------------------- */
2154 void WaitForEventToContinue()
2156 boolean still_wait = TRUE;
2158 /* simulate releasing mouse button over last gadget, if still pressed */
2160 HandleGadgets(-1, -1, 0);
2162 button_status = MB_RELEASED;
2174 case EVENT_BUTTONPRESS:
2175 case EVENT_KEYPRESS:
2179 case EVENT_KEYRELEASE:
2180 ClearPlayerAction();
2184 HandleOtherEvents(&event);
2188 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2195 /* don't eat all CPU time */
2200 #define MAX_REQUEST_LINES 13
2201 #define MAX_REQUEST_LINE_FONT1_LEN 7
2202 #define MAX_REQUEST_LINE_FONT2_LEN 10
2204 boolean Request(char *text, unsigned int req_state)
2206 int mx, my, ty, result = -1;
2207 unsigned int old_door_state;
2208 int last_game_status = game_status; /* save current game status */
2209 int max_request_line_len = MAX_REQUEST_LINE_FONT1_LEN;
2210 int font_nr = FONT_TEXT_2;
2211 int max_word_len = 0;
2214 for (text_ptr = text; *text_ptr; text_ptr++)
2216 max_word_len = (*text_ptr != ' ' ? max_word_len + 1 : 0);
2218 if (max_word_len > MAX_REQUEST_LINE_FONT1_LEN)
2220 max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
2221 font_nr = FONT_LEVEL_NUMBER;
2228 if (game_status == GAME_MODE_PLAYING &&
2229 level.game_engine_type == GAME_ENGINE_TYPE_EM)
2230 BlitScreenToBitmap_EM(backbuffer);
2234 /* disable deactivated drawing when quick-loading level tape recording */
2235 if (tape.playing && tape.deactivate_display)
2236 TapeDeactivateDisplayOff(TRUE);
2240 SetMouseCursor(CURSOR_DEFAULT);
2243 #if defined(NETWORK_AVALIABLE)
2244 /* pause network game while waiting for request to answer */
2245 if (options.network &&
2246 game_status == GAME_MODE_PLAYING &&
2247 req_state & REQUEST_WAIT_FOR_INPUT)
2248 SendToServer_PausePlaying();
2251 old_door_state = GetDoorState();
2253 /* simulate releasing mouse button over last gadget, if still pressed */
2255 HandleGadgets(-1, -1, 0);
2259 if (old_door_state & DOOR_OPEN_1)
2261 CloseDoor(DOOR_CLOSE_1);
2263 /* save old door content */
2264 BlitBitmap(bitmap_db_door, bitmap_db_door,
2265 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
2266 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
2269 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
2271 /* clear door drawing field */
2272 DrawBackground(DX, DY, DXSIZE, DYSIZE);
2274 /* force DOOR font on preview level */
2275 game_status = GAME_MODE_PSEUDO_DOOR;
2277 /* write text for request */
2278 for (ty = 0; ty < MAX_REQUEST_LINES; ty++)
2280 char text_line[max_request_line_len + 1];
2286 for (tl = 0, tx = 0; tx < max_request_line_len; tl++, tx++)
2289 if (!tc || tc == ' ')
2300 strncpy(text_line, text, tl);
2303 DrawText(DX + (DXSIZE - tl * getFontWidth(font_nr)) / 2,
2304 DY + 8 + ty * (getFontHeight(font_nr) + 2),
2305 text_line, font_nr);
2307 text += tl + (tc == ' ' ? 1 : 0);
2310 game_status = last_game_status; /* restore current game status */
2312 if (req_state & REQ_ASK)
2314 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
2315 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
2317 else if (req_state & REQ_CONFIRM)
2319 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
2321 else if (req_state & REQ_PLAYER)
2323 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
2324 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
2325 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
2326 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
2329 /* copy request gadgets to door backbuffer */
2330 BlitBitmap(drawto, bitmap_db_door,
2331 DX, DY, DXSIZE, DYSIZE,
2332 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2334 OpenDoor(DOOR_OPEN_1);
2340 if (!(req_state & REQUEST_WAIT_FOR_INPUT))
2342 SetDrawBackgroundMask(REDRAW_FIELD);
2347 if (game_status != GAME_MODE_MAIN)
2350 button_status = MB_RELEASED;
2352 request_gadget_id = -1;
2354 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
2357 SetMouseCursor(CURSOR_DEFAULT);
2370 case EVENT_BUTTONPRESS:
2371 case EVENT_BUTTONRELEASE:
2372 case EVENT_MOTIONNOTIFY:
2374 if (event.type == EVENT_MOTIONNOTIFY)
2376 if (!PointerInWindow(window))
2377 continue; /* window and pointer are on different screens */
2382 motion_status = TRUE;
2383 mx = ((MotionEvent *) &event)->x;
2384 my = ((MotionEvent *) &event)->y;
2388 motion_status = FALSE;
2389 mx = ((ButtonEvent *) &event)->x;
2390 my = ((ButtonEvent *) &event)->y;
2391 if (event.type == EVENT_BUTTONPRESS)
2392 button_status = ((ButtonEvent *) &event)->button;
2394 button_status = MB_RELEASED;
2397 /* this sets 'request_gadget_id' */
2398 HandleGadgets(mx, my, button_status);
2400 switch(request_gadget_id)
2402 case TOOL_CTRL_ID_YES:
2405 case TOOL_CTRL_ID_NO:
2408 case TOOL_CTRL_ID_CONFIRM:
2409 result = TRUE | FALSE;
2412 case TOOL_CTRL_ID_PLAYER_1:
2415 case TOOL_CTRL_ID_PLAYER_2:
2418 case TOOL_CTRL_ID_PLAYER_3:
2421 case TOOL_CTRL_ID_PLAYER_4:
2432 case EVENT_KEYPRESS:
2433 switch(GetEventKey((KeyEvent *)&event, TRUE))
2446 if (req_state & REQ_PLAYER)
2450 case EVENT_KEYRELEASE:
2451 ClearPlayerAction();
2455 HandleOtherEvents(&event);
2459 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2461 int joy = AnyJoystick();
2463 if (joy & JOY_BUTTON_1)
2465 else if (joy & JOY_BUTTON_2)
2471 /* don't eat all CPU time */
2475 if (game_status != GAME_MODE_MAIN)
2480 if (!(req_state & REQ_STAY_OPEN))
2482 CloseDoor(DOOR_CLOSE_1);
2484 if (((old_door_state & DOOR_OPEN_1) && !(req_state & REQ_STAY_CLOSED)) ||
2485 (req_state & REQ_REOPEN))
2486 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
2491 SetDrawBackgroundMask(REDRAW_FIELD);
2493 #if defined(NETWORK_AVALIABLE)
2494 /* continue network game after request */
2495 if (options.network &&
2496 game_status == GAME_MODE_PLAYING &&
2497 req_state & REQUEST_WAIT_FOR_INPUT)
2498 SendToServer_ContinuePlaying();
2502 /* restore deactivated drawing when quick-loading level tape recording */
2503 if (tape.playing && tape.deactivate_display)
2504 TapeDeactivateDisplayOn();
2510 unsigned int OpenDoor(unsigned int door_state)
2512 if (door_state & DOOR_COPY_BACK)
2514 if (door_state & DOOR_OPEN_1)
2515 BlitBitmap(bitmap_db_door, bitmap_db_door,
2516 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
2517 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2519 if (door_state & DOOR_OPEN_2)
2520 BlitBitmap(bitmap_db_door, bitmap_db_door,
2521 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY2, VXSIZE, VYSIZE,
2522 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2524 door_state &= ~DOOR_COPY_BACK;
2527 return MoveDoor(door_state);
2530 unsigned int CloseDoor(unsigned int door_state)
2532 unsigned int old_door_state = GetDoorState();
2534 if (!(door_state & DOOR_NO_COPY_BACK))
2536 if (old_door_state & DOOR_OPEN_1)
2537 BlitBitmap(backbuffer, bitmap_db_door,
2538 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2540 if (old_door_state & DOOR_OPEN_2)
2541 BlitBitmap(backbuffer, bitmap_db_door,
2542 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2544 door_state &= ~DOOR_NO_COPY_BACK;
2547 return MoveDoor(door_state);
2550 unsigned int GetDoorState()
2552 return MoveDoor(DOOR_GET_STATE);
2555 unsigned int SetDoorState(unsigned int door_state)
2557 return MoveDoor(door_state | DOOR_SET_STATE);
2560 unsigned int MoveDoor(unsigned int door_state)
2562 static int door1 = DOOR_OPEN_1;
2563 static int door2 = DOOR_CLOSE_2;
2564 unsigned long door_delay = 0;
2565 unsigned long door_delay_value;
2568 if (door_state == DOOR_GET_STATE)
2569 return(door1 | door2);
2571 if (door_state & DOOR_SET_STATE)
2573 if (door_state & DOOR_ACTION_1)
2574 door1 = door_state & DOOR_ACTION_1;
2575 if (door_state & DOOR_ACTION_2)
2576 door2 = door_state & DOOR_ACTION_2;
2578 return(door1 | door2);
2581 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2582 door_state &= ~DOOR_OPEN_1;
2583 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2584 door_state &= ~DOOR_CLOSE_1;
2585 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2586 door_state &= ~DOOR_OPEN_2;
2587 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2588 door_state &= ~DOOR_CLOSE_2;
2590 door_delay_value = (door_state & DOOR_ACTION_1 ? door_1.step_delay :
2593 if (setup.quick_doors)
2595 stepsize = 20; /* must be choosen to always draw last frame */
2596 door_delay_value = 0;
2599 StopSound(SND_DOOR_OPENING);
2600 StopSound(SND_DOOR_CLOSING);
2604 if (global.autoplay_leveldir)
2606 door_state |= DOOR_NO_DELAY;
2607 door_state &= ~DOOR_CLOSE_ALL;
2610 if (door_state & DOOR_ACTION)
2612 boolean door_1_done = !(door_state & DOOR_ACTION_1);
2613 boolean door_2_done = !(door_state & DOOR_ACTION_2);
2614 int start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2615 int end = (door_state & DOOR_ACTION_1 &&
2616 door_1.anim_mode == ANIM_VERTICAL ? DYSIZE : DXSIZE);
2619 if (!(door_state & DOOR_NO_DELAY) && !setup.quick_doors)
2621 /* opening door sound has priority over simultaneously closing door */
2622 if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
2623 PlaySoundStereo(SND_DOOR_OPENING, SOUND_MIDDLE);
2624 else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
2625 PlaySoundStereo(SND_DOOR_CLOSING, SOUND_MIDDLE);
2628 for (x = start; x <= end && !(door_1_done && door_2_done); x += stepsize)
2630 Bitmap *bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2631 GC gc = bitmap->stored_clip_gc;
2633 if (door_state & DOOR_ACTION_1)
2635 int a = MIN(x * door_1.step_offset, end);
2636 int i = (door_state & DOOR_OPEN_1 ? end - a : a);
2640 BlitBitmap(bitmap_db_door, drawto,
2641 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i / 2,
2642 DXSIZE, DYSIZE - i / 2, DX, DY);
2644 ClearRectangle(drawto, DX, DY + DYSIZE - i / 2, DXSIZE, i / 2);
2647 if (door_1.anim_mode == ANIM_HORIZONTAL && x <= DXSIZE)
2649 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
2650 int dst1_x = DX + DXSIZE - i, dst1_y = DY;
2651 int src2_x = DXSIZE - i, src2_y = DOOR_GFX_PAGEY1;
2652 int dst2_x = DX, dst2_y = DY;
2653 int width = i, height = DYSIZE;
2655 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2656 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2659 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2660 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2663 else if (door_1.anim_mode == ANIM_VERTICAL && x <= DYSIZE)
2665 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
2666 int dst1_x = DX, dst1_y = DY + DYSIZE - i;
2667 int src2_x = 0, src2_y = DOOR_GFX_PAGEY1 + DYSIZE - i;
2668 int dst2_x = DX, dst2_y = DY;
2669 int width = DXSIZE, height = i;
2671 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2672 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2675 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2676 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2679 else if (x <= DXSIZE) /* ANIM_DEFAULT */
2681 int j = (door_1.anim_mode == ANIM_DEFAULT ? (DXSIZE - i) / 3 : 0);
2683 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2684 BlitBitmapMasked(bitmap, drawto,
2685 DXSIZE, DOOR_GFX_PAGEY1, i, 77,
2686 DX + DXSIZE - i, DY + j);
2687 BlitBitmapMasked(bitmap, drawto,
2688 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
2689 DX + DXSIZE - i, DY + 140 + j);
2690 SetClipOrigin(bitmap, gc, DX - DXSIZE + i,
2691 DY - (DOOR_GFX_PAGEY1 + j));
2692 BlitBitmapMasked(bitmap, drawto,
2693 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
2695 BlitBitmapMasked(bitmap, drawto,
2696 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
2699 BlitBitmapMasked(bitmap, drawto,
2700 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2702 BlitBitmapMasked(bitmap, drawto,
2703 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2705 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2706 BlitBitmapMasked(bitmap, drawto,
2707 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2708 DX + DXSIZE - i, DY + 77 + j);
2709 BlitBitmapMasked(bitmap, drawto,
2710 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2711 DX + DXSIZE - i, DY + 203 + j);
2714 redraw_mask |= REDRAW_DOOR_1;
2715 door_1_done = (a == end);
2718 if (door_state & DOOR_ACTION_2)
2720 int a = MIN(x * door_2.step_offset, VXSIZE);
2721 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - a : a);
2725 BlitBitmap(bitmap_db_door, drawto,
2726 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i / 2,
2727 VXSIZE, VYSIZE - i / 2, VX, VY);
2729 ClearRectangle(drawto, VX, VY + VYSIZE - i / 2, VXSIZE, i / 2);
2732 if (door_2.anim_mode == ANIM_HORIZONTAL && x <= VXSIZE)
2734 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
2735 int dst1_x = VX + VXSIZE - i, dst1_y = VY;
2736 int src2_x = VXSIZE - i, src2_y = DOOR_GFX_PAGEY2;
2737 int dst2_x = VX, dst2_y = VY;
2738 int width = i, height = VYSIZE;
2740 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2741 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2744 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2745 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2748 else if (door_2.anim_mode == ANIM_VERTICAL && x <= VYSIZE)
2750 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
2751 int dst1_x = VX, dst1_y = VY + VYSIZE - i;
2752 int src2_x = 0, src2_y = DOOR_GFX_PAGEY2 + VYSIZE - i;
2753 int dst2_x = VX, dst2_y = VY;
2754 int width = VXSIZE, height = i;
2756 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2757 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2760 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2761 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2764 else if (x <= VXSIZE) /* ANIM_DEFAULT */
2766 int j = (door_2.anim_mode == ANIM_DEFAULT ? (VXSIZE - i) / 3 : 0);
2768 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2769 BlitBitmapMasked(bitmap, drawto,
2770 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
2771 VX + VXSIZE - i, VY + j);
2772 SetClipOrigin(bitmap, gc,
2773 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2774 BlitBitmapMasked(bitmap, drawto,
2775 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
2778 BlitBitmapMasked(bitmap, drawto,
2779 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2780 i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
2781 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2782 BlitBitmapMasked(bitmap, drawto,
2783 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2785 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2788 redraw_mask |= REDRAW_DOOR_2;
2789 door_2_done = (a == VXSIZE);
2794 if (game_status == GAME_MODE_MAIN)
2797 if (!(door_state & DOOR_NO_DELAY))
2798 WaitUntilDelayReached(&door_delay, door_delay_value);
2803 if (setup.quick_doors)
2805 StopSound(SND_DOOR_OPENING);
2806 StopSound(SND_DOOR_CLOSING);
2810 if (door_state & DOOR_ACTION_1)
2811 door1 = door_state & DOOR_ACTION_1;
2812 if (door_state & DOOR_ACTION_2)
2813 door2 = door_state & DOOR_ACTION_2;
2815 return (door1 | door2);
2818 void DrawSpecialEditorDoor()
2820 /* draw bigger toolbox window */
2821 BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
2822 DOOR_GFX_PAGEX7, 0, EXSIZE + 8, 8,
2824 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2825 EX - 4, VY - 4, EXSIZE + 8, EYSIZE - VYSIZE + 4,
2828 redraw_mask |= REDRAW_ALL;
2831 void UndrawSpecialEditorDoor()
2833 /* draw normal tape recorder window */
2834 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2835 EX - 4, EY - 12, EXSIZE + 8, EYSIZE - VYSIZE + 12,
2838 redraw_mask |= REDRAW_ALL;
2842 /* ---------- new tool button stuff ---------------------------------------- */
2844 /* graphic position values for tool buttons */
2845 #define TOOL_BUTTON_YES_XPOS 2
2846 #define TOOL_BUTTON_YES_YPOS 250
2847 #define TOOL_BUTTON_YES_GFX_YPOS 0
2848 #define TOOL_BUTTON_YES_XSIZE 46
2849 #define TOOL_BUTTON_YES_YSIZE 28
2850 #define TOOL_BUTTON_NO_XPOS 52
2851 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2852 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2853 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2854 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2855 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2856 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2857 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2858 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2859 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2860 #define TOOL_BUTTON_PLAYER_XSIZE 30
2861 #define TOOL_BUTTON_PLAYER_YSIZE 30
2862 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2863 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2864 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2865 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2866 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2867 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2868 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2869 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2870 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2871 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2872 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2873 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2874 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2875 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2876 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2877 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2878 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2879 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2880 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2881 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2890 } toolbutton_info[NUM_TOOL_BUTTONS] =
2893 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2894 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2895 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2900 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2901 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2902 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2907 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2908 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2909 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2910 TOOL_CTRL_ID_CONFIRM,
2914 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2915 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2916 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2917 TOOL_CTRL_ID_PLAYER_1,
2921 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2922 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2923 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2924 TOOL_CTRL_ID_PLAYER_2,
2928 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2929 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2930 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2931 TOOL_CTRL_ID_PLAYER_3,
2935 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2936 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2937 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2938 TOOL_CTRL_ID_PLAYER_4,
2943 void CreateToolButtons()
2947 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2949 Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2950 Bitmap *deco_bitmap = None;
2951 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2952 struct GadgetInfo *gi;
2953 unsigned long event_mask;
2954 int gd_xoffset, gd_yoffset;
2955 int gd_x1, gd_x2, gd_y;
2958 event_mask = GD_EVENT_RELEASED;
2960 gd_xoffset = toolbutton_info[i].xpos;
2961 gd_yoffset = toolbutton_info[i].ypos;
2962 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2963 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2964 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2966 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2968 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
2970 getMiniGraphicSource(PLAYER_NR_GFX(IMG_PLAYER_1, player_nr),
2971 &deco_bitmap, &deco_x, &deco_y);
2972 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2973 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2976 gi = CreateGadget(GDI_CUSTOM_ID, id,
2977 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2978 GDI_X, DX + toolbutton_info[i].x,
2979 GDI_Y, DY + toolbutton_info[i].y,
2980 GDI_WIDTH, toolbutton_info[i].width,
2981 GDI_HEIGHT, toolbutton_info[i].height,
2982 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2983 GDI_STATE, GD_BUTTON_UNPRESSED,
2984 GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
2985 GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
2986 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
2987 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2988 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2989 GDI_DECORATION_SHIFTING, 1, 1,
2990 GDI_EVENT_MASK, event_mask,
2991 GDI_CALLBACK_ACTION, HandleToolButtons,
2995 Error(ERR_EXIT, "cannot create gadget");
2997 tool_gadget[id] = gi;
3001 void FreeToolButtons()
3005 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
3006 FreeGadget(tool_gadget[i]);
3009 static void UnmapToolButtons()
3013 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
3014 UnmapGadget(tool_gadget[i]);
3017 static void HandleToolButtons(struct GadgetInfo *gi)
3019 request_gadget_id = gi->custom_id;
3024 static struct Mapping_EM_to_RND_object
3027 boolean is_rnd_to_em_mapping; /* unique mapping EM <-> RND */
3028 boolean is_backside; /* backside of moving element */
3034 em_object_mapping_list[] =
3037 Xblank, TRUE, FALSE,
3041 Yacid_splash_eB, FALSE, FALSE,
3042 EL_ACID_SPLASH_RIGHT, -1, -1
3045 Yacid_splash_wB, FALSE, FALSE,
3046 EL_ACID_SPLASH_LEFT, -1, -1
3049 #ifdef EM_ENGINE_BAD_ROLL
3051 Xstone_force_e, FALSE, FALSE,
3052 EL_ROCK, -1, MV_BIT_RIGHT
3055 Xstone_force_w, FALSE, FALSE,
3056 EL_ROCK, -1, MV_BIT_LEFT
3059 Xnut_force_e, FALSE, FALSE,
3060 EL_NUT, -1, MV_BIT_RIGHT
3063 Xnut_force_w, FALSE, FALSE,
3064 EL_NUT, -1, MV_BIT_LEFT
3067 Xspring_force_e, FALSE, FALSE,
3068 EL_SPRING, -1, MV_BIT_RIGHT
3071 Xspring_force_w, FALSE, FALSE,
3072 EL_SPRING, -1, MV_BIT_LEFT
3075 Xemerald_force_e, FALSE, FALSE,
3076 EL_EMERALD, -1, MV_BIT_RIGHT
3079 Xemerald_force_w, FALSE, FALSE,
3080 EL_EMERALD, -1, MV_BIT_LEFT
3083 Xdiamond_force_e, FALSE, FALSE,
3084 EL_DIAMOND, -1, MV_BIT_RIGHT
3087 Xdiamond_force_w, FALSE, FALSE,
3088 EL_DIAMOND, -1, MV_BIT_LEFT
3091 Xbomb_force_e, FALSE, FALSE,
3092 EL_BOMB, -1, MV_BIT_RIGHT
3095 Xbomb_force_w, FALSE, FALSE,
3096 EL_BOMB, -1, MV_BIT_LEFT
3098 #endif /* EM_ENGINE_BAD_ROLL */
3101 Xstone, TRUE, FALSE,
3105 Xstone_pause, FALSE, FALSE,
3109 Xstone_fall, FALSE, FALSE,
3113 Ystone_s, FALSE, FALSE,
3114 EL_ROCK, ACTION_FALLING, -1
3117 Ystone_sB, FALSE, TRUE,
3118 EL_ROCK, ACTION_FALLING, -1
3121 Ystone_e, FALSE, FALSE,
3122 EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT
3125 Ystone_eB, FALSE, TRUE,
3126 EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT
3129 Ystone_w, FALSE, FALSE,
3130 EL_ROCK, ACTION_MOVING, MV_BIT_LEFT
3133 Ystone_wB, FALSE, TRUE,
3134 EL_ROCK, ACTION_MOVING, MV_BIT_LEFT
3141 Xnut_pause, FALSE, FALSE,
3145 Xnut_fall, FALSE, FALSE,
3149 Ynut_s, FALSE, FALSE,
3150 EL_NUT, ACTION_FALLING, -1
3153 Ynut_sB, FALSE, TRUE,
3154 EL_NUT, ACTION_FALLING, -1
3157 Ynut_e, FALSE, FALSE,
3158 EL_NUT, ACTION_MOVING, MV_BIT_RIGHT
3161 Ynut_eB, FALSE, TRUE,
3162 EL_NUT, ACTION_MOVING, MV_BIT_RIGHT
3165 Ynut_w, FALSE, FALSE,
3166 EL_NUT, ACTION_MOVING, MV_BIT_LEFT
3169 Ynut_wB, FALSE, TRUE,
3170 EL_NUT, ACTION_MOVING, MV_BIT_LEFT
3173 Xbug_n, TRUE, FALSE,
3177 Xbug_e, TRUE, FALSE,
3178 EL_BUG_RIGHT, -1, -1
3181 Xbug_s, TRUE, FALSE,
3185 Xbug_w, TRUE, FALSE,
3189 Xbug_gon, FALSE, FALSE,
3193 Xbug_goe, FALSE, FALSE,
3194 EL_BUG_RIGHT, -1, -1
3197 Xbug_gos, FALSE, FALSE,
3201 Xbug_gow, FALSE, FALSE,
3205 Ybug_n, FALSE, FALSE,
3206 EL_BUG, ACTION_MOVING, MV_BIT_UP
3209 Ybug_nB, FALSE, TRUE,
3210 EL_BUG, ACTION_MOVING, MV_BIT_UP
3213 Ybug_e, FALSE, FALSE,
3214 EL_BUG, ACTION_MOVING, MV_BIT_RIGHT
3217 Ybug_eB, FALSE, TRUE,
3218 EL_BUG, ACTION_MOVING, MV_BIT_RIGHT
3221 Ybug_s, FALSE, FALSE,
3222 EL_BUG, ACTION_MOVING, MV_BIT_DOWN
3225 Ybug_sB, FALSE, TRUE,
3226 EL_BUG, ACTION_MOVING, MV_BIT_DOWN
3229 Ybug_w, FALSE, FALSE,
3230 EL_BUG, ACTION_MOVING, MV_BIT_LEFT
3233 Ybug_wB, FALSE, TRUE,
3234 EL_BUG, ACTION_MOVING, MV_BIT_LEFT
3237 Ybug_w_n, FALSE, FALSE,
3238 EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_UP
3241 Ybug_n_e, FALSE, FALSE,
3242 EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3245 Ybug_e_s, FALSE, FALSE,
3246 EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
3249 Ybug_s_w, FALSE, FALSE,
3250 EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3253 Ybug_e_n, FALSE, FALSE,
3254 EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
3257 Ybug_s_e, FALSE, FALSE,
3258 EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3261 Ybug_w_s, FALSE, FALSE,
3262 EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
3265 Ybug_n_w, FALSE, FALSE,
3266 EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3269 Ybug_stone, FALSE, FALSE,
3270 EL_BUG, ACTION_SMASHED_BY_ROCK, -1
3273 Ybug_spring, FALSE, FALSE,
3274 EL_BUG, ACTION_SMASHED_BY_SPRING, -1
3277 Xtank_n, TRUE, FALSE,
3278 EL_SPACESHIP_UP, -1, -1
3281 Xtank_e, TRUE, FALSE,
3282 EL_SPACESHIP_RIGHT, -1, -1
3285 Xtank_s, TRUE, FALSE,
3286 EL_SPACESHIP_DOWN, -1, -1
3289 Xtank_w, TRUE, FALSE,
3290 EL_SPACESHIP_LEFT, -1, -1
3293 Xtank_gon, FALSE, FALSE,
3294 EL_SPACESHIP_UP, -1, -1
3297 Xtank_goe, FALSE, FALSE,
3298 EL_SPACESHIP_RIGHT, -1, -1
3301 Xtank_gos, FALSE, FALSE,
3302 EL_SPACESHIP_DOWN, -1, -1
3305 Xtank_gow, FALSE, FALSE,
3306 EL_SPACESHIP_LEFT, -1, -1
3309 Ytank_n, FALSE, FALSE,
3310 EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP
3313 Ytank_nB, FALSE, TRUE,
3314 EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP
3317 Ytank_e, FALSE, FALSE,
3318 EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT
3321 Ytank_eB, FALSE, TRUE,
3322 EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT
3325 Ytank_s, FALSE, FALSE,
3326 EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN
3329 Ytank_sB, FALSE, TRUE,
3330 EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN
3333 Ytank_w, FALSE, FALSE,
3334 EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT
3337 Ytank_wB, FALSE, TRUE,
3338 EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT
3341 Ytank_w_n, FALSE, FALSE,
3342 EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_UP
3345 Ytank_n_e, FALSE, FALSE,
3346 EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3349 Ytank_e_s, FALSE, FALSE,
3350 EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
3353 Ytank_s_w, FALSE, FALSE,
3354 EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3357 Ytank_e_n, FALSE, FALSE,
3358 EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
3361 Ytank_s_e, FALSE, FALSE,
3362 EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3365 Ytank_w_s, FALSE, FALSE,
3366 EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
3369 Ytank_n_w, FALSE, FALSE,
3370 EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3373 Ytank_stone, FALSE, FALSE,
3374 EL_SPACESHIP, ACTION_SMASHED_BY_ROCK, -1
3377 Ytank_spring, FALSE, FALSE,
3378 EL_SPACESHIP, ACTION_SMASHED_BY_SPRING, -1
3381 Xandroid, TRUE, FALSE,
3382 EL_EMC_ANDROID, ACTION_ACTIVE, -1
3385 Xandroid_1_n, FALSE, FALSE,
3386 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_UP
3389 Xandroid_2_n, FALSE, FALSE,
3390 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_UP
3393 Xandroid_1_e, FALSE, FALSE,
3394 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_RIGHT
3397 Xandroid_2_e, FALSE, FALSE,
3398 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_RIGHT
3401 Xandroid_1_w, FALSE, FALSE,
3402 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_LEFT
3405 Xandroid_2_w, FALSE, FALSE,
3406 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_LEFT
3409 Xandroid_1_s, FALSE, FALSE,
3410 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_DOWN
3413 Xandroid_2_s, FALSE, FALSE,
3414 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_DOWN
3417 Yandroid_n, FALSE, FALSE,
3418 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_UP
3421 Yandroid_nB, FALSE, TRUE,
3422 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_UP
3425 Yandroid_ne, FALSE, FALSE,
3426 EL_EMC_ANDROID, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3429 Yandroid_neB, FALSE, TRUE,
3430 EL_EMC_ANDROID, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3433 Yandroid_e, FALSE, FALSE,
3434 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_RIGHT
3437 Yandroid_eB, FALSE, TRUE,
3438 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_RIGHT
3441 Yandroid_se, FALSE, FALSE,
3442 EL_EMC_ANDROID, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3445 Yandroid_seB, FALSE, TRUE,
3446 EL_EMC_ANDROID, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3449 Yandroid_s, FALSE, FALSE,
3450 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_DOWN
3453 Yandroid_sB, FALSE, TRUE,
3454 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_DOWN
3457 Yandroid_sw, FALSE, FALSE,
3458 EL_EMC_ANDROID, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3461 Yandroid_swB, FALSE, TRUE,
3462 EL_EMC_ANDROID, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3465 Yandroid_w, FALSE, FALSE,
3466 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_LEFT
3469 Yandroid_wB, FALSE, TRUE,
3470 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_LEFT
3473 Yandroid_nw, FALSE, FALSE,
3474 EL_EMC_ANDROID, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3477 Yandroid_nwB, FALSE, TRUE,
3478 EL_EMC_ANDROID, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3481 Xspring, TRUE, FALSE,
3485 Xspring_pause, FALSE, FALSE,
3489 Xspring_e, FALSE, FALSE,
3493 Xspring_w, FALSE, FALSE,
3497 Xspring_fall, FALSE, FALSE,
3501 Yspring_s, FALSE, FALSE,
3502 EL_SPRING, ACTION_FALLING, -1
3505 Yspring_sB, FALSE, TRUE,
3506 EL_SPRING, ACTION_FALLING, -1
3509 Yspring_e, FALSE, FALSE,
3510 EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT
3513 Yspring_eB, FALSE, TRUE,
3514 EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT
3517 Yspring_w, FALSE, FALSE,
3518 EL_SPRING, ACTION_MOVING, MV_BIT_LEFT
3521 Yspring_wB, FALSE, TRUE,
3522 EL_SPRING, ACTION_MOVING, MV_BIT_LEFT
3525 Yspring_kill_e, FALSE, FALSE,
3526 EL_ROBOT, ACTION_SLURPED_BY_SPRING, MV_BIT_RIGHT
3529 Yspring_kill_eB, FALSE, TRUE,
3530 EL_ROBOT, ACTION_SLURPED_BY_SPRING, MV_BIT_RIGHT
3533 Yspring_kill_w, FALSE, FALSE,
3534 EL_ROBOT, ACTION_SLURPED_BY_SPRING, MV_BIT_LEFT
3537 Yspring_kill_wB, FALSE, TRUE,
3538 EL_ROBOT, ACTION_SLURPED_BY_SPRING, MV_BIT_LEFT
3541 Xeater_n, TRUE, FALSE,
3545 Xeater_e, FALSE, FALSE,
3549 Xeater_w, FALSE, FALSE,
3553 Xeater_s, FALSE, FALSE,
3557 Yeater_n, FALSE, FALSE,
3558 EL_YAMYAM, ACTION_MOVING, MV_BIT_UP
3561 Yeater_nB, FALSE, TRUE,
3562 EL_YAMYAM, ACTION_MOVING, MV_BIT_UP
3565 Yeater_e, FALSE, FALSE,
3566 EL_YAMYAM, ACTION_MOVING, MV_BIT_RIGHT
3569 Yeater_eB, FALSE, TRUE,
3570 EL_YAMYAM, ACTION_MOVING, MV_BIT_RIGHT
3573 Yeater_s, FALSE, FALSE,
3574 EL_YAMYAM, ACTION_MOVING, MV_BIT_DOWN
3577 Yeater_sB, FALSE, TRUE,
3578 EL_YAMYAM, ACTION_MOVING, MV_BIT_DOWN
3581 Yeater_w, FALSE, FALSE,
3582 EL_YAMYAM, ACTION_MOVING, MV_BIT_LEFT
3585 Yeater_wB, FALSE, TRUE,
3586 EL_YAMYAM, ACTION_MOVING, MV_BIT_LEFT
3589 Yeater_stone, FALSE, FALSE,
3590 EL_YAMYAM, ACTION_SMASHED_BY_ROCK, -1
3593 Yeater_spring, FALSE, FALSE,
3594 EL_YAMYAM, ACTION_SMASHED_BY_SPRING, -1
3597 Xalien, TRUE, FALSE,
3601 Xalien_pause, FALSE, FALSE,
3605 Yalien_n, FALSE, FALSE,
3606 EL_ROBOT, ACTION_MOVING, MV_BIT_UP
3609 Yalien_nB, FALSE, TRUE,
3610 EL_ROBOT, ACTION_MOVING, MV_BIT_UP
3613 Yalien_e, FALSE, FALSE,
3614 EL_ROBOT, ACTION_MOVING, MV_BIT_RIGHT
3617 Yalien_eB, FALSE, TRUE,
3618 EL_ROBOT, ACTION_MOVING, MV_BIT_RIGHT
3621 Yalien_s, FALSE, FALSE,
3622 EL_ROBOT, ACTION_MOVING, MV_BIT_DOWN
3625 Yalien_sB, FALSE, TRUE,
3626 EL_ROBOT, ACTION_MOVING, MV_BIT_DOWN
3629 Yalien_w, FALSE, FALSE,
3630 EL_ROBOT, ACTION_MOVING, MV_BIT_LEFT
3633 Yalien_wB, FALSE, TRUE,
3634 EL_ROBOT, ACTION_MOVING, MV_BIT_LEFT
3637 Yalien_stone, FALSE, FALSE,
3638 EL_ROBOT, ACTION_SMASHED_BY_ROCK, -1
3641 Yalien_spring, FALSE, FALSE,
3642 EL_ROBOT, ACTION_SMASHED_BY_SPRING, -1
3645 Xemerald, TRUE, FALSE,
3649 Xemerald_pause, FALSE, FALSE,
3653 Xemerald_fall, FALSE, FALSE,
3657 Xemerald_shine, FALSE, FALSE,
3658 EL_EMERALD, ACTION_TWINKLING, -1
3661 Yemerald_s, FALSE, FALSE,
3662 EL_EMERALD, ACTION_FALLING, -1
3665 Yemerald_sB, FALSE, TRUE,
3666 EL_EMERALD, ACTION_FALLING, -1
3669 Yemerald_e, FALSE, FALSE,
3670 EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT
3673 Yemerald_eB, FALSE, TRUE,
3674 EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT
3677 Yemerald_w, FALSE, FALSE,
3678 EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT
3681 Yemerald_wB, FALSE, TRUE,
3682 EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT
3685 Yemerald_eat, FALSE, FALSE,
3686 EL_EMERALD, ACTION_COLLECTING, -1
3689 Yemerald_stone, FALSE, FALSE,
3690 EL_NUT, ACTION_BREAKING, -1
3693 Xdiamond, TRUE, FALSE,
3697 Xdiamond_pause, FALSE, FALSE,
3701 Xdiamond_fall, FALSE, FALSE,
3705 Xdiamond_shine, FALSE, FALSE,
3706 EL_DIAMOND, ACTION_TWINKLING, -1
3709 Ydiamond_s, FALSE, FALSE,
3710 EL_DIAMOND, ACTION_FALLING, -1
3713 Ydiamond_sB, FALSE, TRUE,
3714 EL_DIAMOND, ACTION_FALLING, -1
3717 Ydiamond_e, FALSE, FALSE,
3718 EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT
3721 Ydiamond_eB, FALSE, TRUE,
3722 EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT
3725 Ydiamond_w, FALSE, FALSE,
3726 EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT
3729 Ydiamond_wB, FALSE, TRUE,
3730 EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT
3733 Ydiamond_eat, FALSE, FALSE,
3734 EL_DIAMOND, ACTION_COLLECTING, -1
3737 Ydiamond_stone, FALSE, FALSE,
3738 EL_DIAMOND, ACTION_SMASHED_BY_ROCK, -1
3741 Xdrip_fall, TRUE, FALSE,
3742 EL_AMOEBA_DROP, -1, -1
3745 Xdrip_stretch, FALSE, FALSE,
3746 EL_AMOEBA_DROP, ACTION_FALLING, -1
3749 Xdrip_stretchB, FALSE, TRUE,
3750 EL_AMOEBA_DROP, ACTION_FALLING, -1
3753 Xdrip_eat, FALSE, FALSE,
3754 EL_AMOEBA_DROP, ACTION_GROWING, -1
3757 Ydrip_s1, FALSE, FALSE,
3758 EL_AMOEBA_DROP, ACTION_FALLING, -1
3761 Ydrip_s1B, FALSE, TRUE,
3762 EL_AMOEBA_DROP, ACTION_FALLING, -1
3765 Ydrip_s2, FALSE, FALSE,
3766 EL_AMOEBA_DROP, ACTION_FALLING, -1
3769 Ydrip_s2B, FALSE, TRUE,
3770 EL_AMOEBA_DROP, ACTION_FALLING, -1
3777 Xbomb_pause, FALSE, FALSE,
3781 Xbomb_fall, FALSE, FALSE,
3785 Ybomb_s, FALSE, FALSE,
3786 EL_BOMB, ACTION_FALLING, -1
3789 Ybomb_sB, FALSE, TRUE,
3790 EL_BOMB, ACTION_FALLING, -1
3793 Ybomb_e, FALSE, FALSE,
3794 EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT
3797 Ybomb_eB, FALSE, TRUE,
3798 EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT
3801 Ybomb_w, FALSE, FALSE,
3802 EL_BOMB, ACTION_MOVING, MV_BIT_LEFT
3805 Ybomb_wB, FALSE, TRUE,
3806 EL_BOMB, ACTION_MOVING, MV_BIT_LEFT
3809 Ybomb_eat, FALSE, FALSE,
3810 EL_BOMB, ACTION_SMASHED_BY_ROCK, -1
3813 Xballoon, TRUE, FALSE,
3817 Yballoon_n, FALSE, FALSE,
3818 EL_BALLOON, ACTION_MOVING, MV_BIT_UP
3821 Yballoon_nB, FALSE, TRUE,
3822 EL_BALLOON, ACTION_MOVING, MV_BIT_UP
3825 Yballoon_e, FALSE, FALSE,
3826 EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT
3829 Yballoon_eB, FALSE, TRUE,
3830 EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT
3833 Yballoon_s, FALSE, FALSE,
3834 EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN
3837 Yballoon_sB, FALSE, TRUE,
3838 EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN
3841 Yballoon_w, FALSE, FALSE,
3842 EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT
3845 Yballoon_wB, FALSE, TRUE,
3846 EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT
3849 Xgrass, TRUE, FALSE,
3850 EL_EMC_GRASS, -1, -1
3853 Ygrass_nB, FALSE, FALSE,
3854 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_UP
3857 Ygrass_eB, FALSE, FALSE,
3858 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_RIGHT
3861 Ygrass_sB, FALSE, FALSE,
3862 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_DOWN
3865 Ygrass_wB, FALSE, FALSE,
3866 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_LEFT
3873 Ydirt_nB, FALSE, FALSE,
3874 EL_SAND, ACTION_DIGGING, MV_BIT_UP
3877 Ydirt_eB, FALSE, FALSE,
3878 EL_SAND, ACTION_DIGGING, MV_BIT_RIGHT
3881 Ydirt_sB, FALSE, FALSE,
3882 EL_SAND, ACTION_DIGGING, MV_BIT_DOWN
3885 Ydirt_wB, FALSE, FALSE,
3886 EL_SAND, ACTION_DIGGING, MV_BIT_LEFT
3889 Xacid_ne, TRUE, FALSE,
3890 EL_ACID_POOL_TOPRIGHT, -1, -1
3893 Xacid_se, TRUE, FALSE,
3894 EL_ACID_POOL_BOTTOMRIGHT, -1, -1
3897 Xacid_s, TRUE, FALSE,
3898 EL_ACID_POOL_BOTTOM, -1, -1
3901 Xacid_sw, TRUE, FALSE,
3902 EL_ACID_POOL_BOTTOMLEFT, -1, -1
3905 Xacid_nw, TRUE, FALSE,
3906 EL_ACID_POOL_TOPLEFT, -1, -1
3909 Xacid_1, TRUE, FALSE,
3913 Xacid_2, FALSE, FALSE,
3917 Xacid_3, FALSE, FALSE,
3921 Xacid_4, FALSE, FALSE,
3925 Xacid_5, FALSE, FALSE,
3929 Xacid_6, FALSE, FALSE,
3933 Xacid_7, FALSE, FALSE,
3937 Xacid_8, FALSE, FALSE,
3941 Xball_1, TRUE, FALSE,
3942 EL_EMC_MAGIC_BALL, -1, -1
3945 Xball_1B, FALSE, FALSE,
3946 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
3949 Xball_2, FALSE, FALSE,
3950 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
3953 Xball_2B, FALSE, FALSE,
3954 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
3957 Yball_eat, FALSE, FALSE,
3958 EL_EMC_MAGIC_BALL, ACTION_DROPPING, -1
3961 Ykey_1_eat, FALSE, FALSE,
3962 EL_EM_KEY_1, ACTION_COLLECTING, -1
3965 Ykey_2_eat, FALSE, FALSE,
3966 EL_EM_KEY_2, ACTION_COLLECTING, -1
3969 Ykey_3_eat, FALSE, FALSE,
3970 EL_EM_KEY_3, ACTION_COLLECTING, -1
3973 Ykey_4_eat, FALSE, FALSE,
3974 EL_EM_KEY_4, ACTION_COLLECTING, -1
3977 Ykey_5_eat, FALSE, FALSE,
3978 EL_EM_KEY_5, ACTION_COLLECTING, -1
3981 Ykey_6_eat, FALSE, FALSE,
3982 EL_EM_KEY_6, ACTION_COLLECTING, -1
3985 Ykey_7_eat, FALSE, FALSE,
3986 EL_EM_KEY_7, ACTION_COLLECTING, -1
3989 Ykey_8_eat, FALSE, FALSE,
3990 EL_EM_KEY_8, ACTION_COLLECTING, -1
3993 Ylenses_eat, FALSE, FALSE,
3994 EL_EMC_LENSES, ACTION_COLLECTING, -1
3997 Ymagnify_eat, FALSE, FALSE,
3998 EL_EMC_MAGNIFIER, ACTION_COLLECTING, -1
4001 Ygrass_eat, FALSE, FALSE,
4002 EL_EMC_GRASS, ACTION_SNAPPING, -1
4005 Ydirt_eat, FALSE, FALSE,
4006 EL_SAND, ACTION_SNAPPING, -1
4009 Xgrow_ns, TRUE, FALSE,
4010 EL_EXPANDABLE_WALL_VERTICAL, -1, -1
4013 Ygrow_ns_eat, FALSE, FALSE,
4014 EL_EXPANDABLE_WALL_VERTICAL, ACTION_GROWING, -1
4017 Xgrow_ew, TRUE, FALSE,
4018 EL_EXPANDABLE_WALL_HORIZONTAL, -1, -1
4021 Ygrow_ew_eat, FALSE, FALSE,
4022 EL_EXPANDABLE_WALL_HORIZONTAL, ACTION_GROWING, -1
4025 Xwonderwall, TRUE, FALSE,
4026 EL_MAGIC_WALL, -1, -1
4029 XwonderwallB, FALSE, FALSE,
4030 EL_MAGIC_WALL, ACTION_ACTIVE, -1
4033 Xamoeba_1, TRUE, FALSE,
4034 EL_AMOEBA_DRY, ACTION_OTHER, -1
4037 Xamoeba_2, FALSE, FALSE,
4038 EL_AMOEBA_DRY, ACTION_OTHER, -1
4041 Xamoeba_3, FALSE, FALSE,
4042 EL_AMOEBA_DRY, ACTION_OTHER, -1
4045 Xamoeba_4, FALSE, FALSE,
4046 EL_AMOEBA_DRY, ACTION_OTHER, -1
4049 Xamoeba_5, TRUE, FALSE,
4050 EL_AMOEBA_WET, ACTION_OTHER, -1
4053 Xamoeba_6, FALSE, FALSE,
4054 EL_AMOEBA_WET, ACTION_OTHER, -1
4057 Xamoeba_7, FALSE, FALSE,
4058 EL_AMOEBA_WET, ACTION_OTHER, -1
4061 Xamoeba_8, FALSE, FALSE,
4062 EL_AMOEBA_WET, ACTION_OTHER, -1
4065 Xdoor_1, TRUE, FALSE,
4066 EL_EM_GATE_1, -1, -1
4069 Xdoor_2, TRUE, FALSE,
4070 EL_EM_GATE_2, -1, -1
4073 Xdoor_3, TRUE, FALSE,
4074 EL_EM_GATE_3, -1, -1
4077 Xdoor_4, TRUE, FALSE,
4078 EL_EM_GATE_4, -1, -1
4081 Xdoor_5, TRUE, FALSE,
4082 EL_EM_GATE_5, -1, -1
4085 Xdoor_6, TRUE, FALSE,
4086 EL_EM_GATE_6, -1, -1
4089 Xdoor_7, TRUE, FALSE,
4090 EL_EM_GATE_7, -1, -1
4093 Xdoor_8, TRUE, FALSE,
4094 EL_EM_GATE_8, -1, -1
4097 Xkey_1, TRUE, FALSE,
4101 Xkey_2, TRUE, FALSE,
4105 Xkey_3, TRUE, FALSE,
4109 Xkey_4, TRUE, FALSE,
4113 Xkey_5, TRUE, FALSE,
4117 Xkey_6, TRUE, FALSE,
4121 Xkey_7, TRUE, FALSE,
4125 Xkey_8, TRUE, FALSE,
4129 Xwind_n, TRUE, FALSE,
4130 EL_BALLOON_SWITCH_UP, -1, -1
4133 Xwind_e, TRUE, FALSE,
4134 EL_BALLOON_SWITCH_RIGHT, -1, -1
4137 Xwind_s, TRUE, FALSE,
4138 EL_BALLOON_SWITCH_DOWN, -1, -1
4141 Xwind_w, TRUE, FALSE,
4142 EL_BALLOON_SWITCH_LEFT, -1, -1
4145 Xwind_nesw, TRUE, FALSE,
4146 EL_BALLOON_SWITCH_ANY, -1, -1
4149 Xwind_stop, TRUE, FALSE,
4150 EL_BALLOON_SWITCH_NONE, -1, -1
4154 EL_EXIT_CLOSED, -1, -1
4157 Xexit_1, TRUE, FALSE,
4158 EL_EXIT_OPEN, -1, -1
4161 Xexit_2, FALSE, FALSE,
4162 EL_EXIT_OPEN, -1, -1
4165 Xexit_3, FALSE, FALSE,
4166 EL_EXIT_OPEN, -1, -1
4169 Xdynamite, TRUE, FALSE,
4173 Ydynamite_eat, FALSE, FALSE,
4174 EL_DYNAMITE, ACTION_COLLECTING, -1
4177 Xdynamite_1, TRUE, FALSE,
4178 EL_DYNAMITE_ACTIVE, -1, -1
4181 Xdynamite_2, FALSE, FALSE,
4182 EL_DYNAMITE_ACTIVE, -1, -1
4185 Xdynamite_3, FALSE, FALSE,
4186 EL_DYNAMITE_ACTIVE, -1, -1
4189 Xdynamite_4, FALSE, FALSE,
4190 EL_DYNAMITE_ACTIVE, -1, -1
4193 Xbumper, TRUE, FALSE,
4194 EL_EMC_SPRING_BUMPER, -1, -1
4197 XbumperB, FALSE, FALSE,
4198 EL_EMC_SPRING_BUMPER, ACTION_ACTIVE, -1
4201 Xwheel, TRUE, FALSE,
4202 EL_ROBOT_WHEEL, -1, -1
4205 XwheelB, FALSE, FALSE,
4206 EL_ROBOT_WHEEL, ACTION_ACTIVE, -1
4209 Xswitch, TRUE, FALSE,
4210 EL_EMC_MAGIC_BALL_SWITCH, -1, -1
4213 XswitchB, FALSE, FALSE,
4214 EL_EMC_MAGIC_BALL_SWITCH, ACTION_ACTIVE, -1
4218 EL_QUICKSAND_EMPTY, -1, -1
4221 Xsand_stone, TRUE, FALSE,
4222 EL_QUICKSAND_FULL, -1, -1
4225 Xsand_stonein_1, FALSE, FALSE,
4226 EL_ROCK, ACTION_FILLING, -1
4229 Xsand_stonein_2, FALSE, FALSE,
4230 EL_ROCK, ACTION_FILLING, -1
4233 Xsand_stonein_3, FALSE, FALSE,
4234 EL_ROCK, ACTION_FILLING, -1
4237 Xsand_stonein_4, FALSE, FALSE,
4238 EL_ROCK, ACTION_FILLING, -1
4241 Xsand_stonesand_1, FALSE, FALSE,
4242 EL_QUICKSAND_FULL, -1, -1
4245 Xsand_stonesand_2, FALSE, FALSE,
4246 EL_QUICKSAND_FULL, -1, -1
4249 Xsand_stonesand_3, FALSE, FALSE,
4250 EL_QUICKSAND_FULL, -1, -1
4253 Xsand_stonesand_4, FALSE, FALSE,
4254 EL_QUICKSAND_FULL, -1, -1
4257 Xsand_stoneout_1, FALSE, FALSE,
4258 EL_ROCK, ACTION_EMPTYING, -1
4261 Xsand_stoneout_2, FALSE, FALSE,
4262 EL_ROCK, ACTION_EMPTYING, -1
4265 Xsand_sandstone_1, FALSE, FALSE,
4266 EL_QUICKSAND_FULL, -1, -1
4269 Xsand_sandstone_2, FALSE, FALSE,
4270 EL_QUICKSAND_FULL, -1, -1
4273 Xsand_sandstone_3, FALSE, FALSE,
4274 EL_QUICKSAND_FULL, -1, -1
4277 Xsand_sandstone_4, FALSE, FALSE,
4278 EL_QUICKSAND_FULL, -1, -1
4281 Xplant, TRUE, FALSE,
4282 EL_EMC_PLANT, -1, -1
4285 Yplant, FALSE, FALSE,
4286 EL_EMC_PLANT, -1, -1
4289 Xlenses, TRUE, FALSE,
4290 EL_EMC_LENSES, -1, -1
4293 Xmagnify, TRUE, FALSE,
4294 EL_EMC_MAGNIFIER, -1, -1
4297 Xdripper, TRUE, FALSE,
4298 EL_EMC_DRIPPER, -1, -1
4301 XdripperB, FALSE, FALSE,
4302 EL_EMC_DRIPPER, ACTION_ACTIVE, -1
4305 Xfake_blank, TRUE, FALSE,
4306 EL_INVISIBLE_WALL, -1, -1
4309 Xfake_blankB, FALSE, FALSE,
4310 EL_INVISIBLE_WALL, ACTION_ACTIVE, -1
4313 Xfake_grass, TRUE, FALSE,
4314 EL_EMC_FAKE_GRASS, -1, -1
4317 Xfake_grassB, FALSE, FALSE,
4318 EL_EMC_FAKE_GRASS, ACTION_ACTIVE, -1
4321 Xfake_door_1, TRUE, FALSE,
4322 EL_EM_GATE_1_GRAY, -1, -1
4325 Xfake_door_2, TRUE, FALSE,
4326 EL_EM_GATE_2_GRAY, -1, -1
4329 Xfake_door_3, TRUE, FALSE,
4330 EL_EM_GATE_3_GRAY, -1, -1
4333 Xfake_door_4, TRUE, FALSE,
4334 EL_EM_GATE_4_GRAY, -1, -1
4337 Xfake_door_5, TRUE, FALSE,
4338 EL_EM_GATE_5_GRAY, -1, -1
4341 Xfake_door_6, TRUE, FALSE,
4342 EL_EM_GATE_6_GRAY, -1, -1
4345 Xfake_door_7, TRUE, FALSE,
4346 EL_EM_GATE_7_GRAY, -1, -1
4349 Xfake_door_8, TRUE, FALSE,
4350 EL_EM_GATE_8_GRAY, -1, -1
4353 Xsteel_1, TRUE, FALSE,
4354 EL_STEELWALL, -1, -1
4357 Xsteel_2, TRUE, FALSE,
4358 EL_EMC_STEELWALL_2, -1, -1
4361 Xsteel_3, TRUE, FALSE,
4362 EL_EMC_STEELWALL_3, -1, -1
4365 Xsteel_4, TRUE, FALSE,
4366 EL_EMC_STEELWALL_4, -1, -1
4369 Xwall_1, TRUE, FALSE,
4373 Xwall_2, TRUE, FALSE,
4374 EL_EMC_WALL_14, -1, -1
4377 Xwall_3, TRUE, FALSE,
4378 EL_EMC_WALL_15, -1, -1
4381 Xwall_4, TRUE, FALSE,
4382 EL_EMC_WALL_16, -1, -1
4385 Xround_wall_1, TRUE, FALSE,
4386 EL_WALL_SLIPPERY, -1, -1
4389 Xround_wall_2, TRUE, FALSE,
4390 EL_EMC_WALL_SLIPPERY_2, -1, -1
4393 Xround_wall_3, TRUE, FALSE,
4394 EL_EMC_WALL_SLIPPERY_3, -1, -1
4397 Xround_wall_4, TRUE, FALSE,
4398 EL_EMC_WALL_SLIPPERY_4, -1, -1
4401 Xdecor_1, TRUE, FALSE,
4402 EL_EMC_WALL_8, -1, -1
4405 Xdecor_2, TRUE, FALSE,
4406 EL_EMC_WALL_6, -1, -1
4409 Xdecor_3, TRUE, FALSE,
4410 EL_EMC_WALL_4, -1, -1
4413 Xdecor_4, TRUE, FALSE,
4414 EL_EMC_WALL_7, -1, -1
4417 Xdecor_5, TRUE, FALSE,
4418 EL_EMC_WALL_5, -1, -1
4421 Xdecor_6, TRUE, FALSE,
4422 EL_EMC_WALL_9, -1, -1
4425 Xdecor_7, TRUE, FALSE,
4426 EL_EMC_WALL_10, -1, -1
4429 Xdecor_8, TRUE, FALSE,
4430 EL_EMC_WALL_1, -1, -1
4433 Xdecor_9, TRUE, FALSE,
4434 EL_EMC_WALL_2, -1, -1
4437 Xdecor_10, TRUE, FALSE,
4438 EL_EMC_WALL_3, -1, -1
4441 Xdecor_11, TRUE, FALSE,
4442 EL_EMC_WALL_11, -1, -1
4445 Xdecor_12, TRUE, FALSE,
4446 EL_EMC_WALL_12, -1, -1
4449 Xalpha_0, TRUE, FALSE,
4450 EL_CHAR('0'), -1, -1
4453 Xalpha_1, TRUE, FALSE,
4454 EL_CHAR('1'), -1, -1
4457 Xalpha_2, TRUE, FALSE,
4458 EL_CHAR('2'), -1, -1
4461 Xalpha_3, TRUE, FALSE,
4462 EL_CHAR('3'), -1, -1
4465 Xalpha_4, TRUE, FALSE,
4466 EL_CHAR('4'), -1, -1
4469 Xalpha_5, TRUE, FALSE,
4470 EL_CHAR('5'), -1, -1
4473 Xalpha_6, TRUE, FALSE,
4474 EL_CHAR('6'), -1, -1
4477 Xalpha_7, TRUE, FALSE,
4478 EL_CHAR('7'), -1, -1
4481 Xalpha_8, TRUE, FALSE,
4482 EL_CHAR('8'), -1, -1
4485 Xalpha_9, TRUE, FALSE,
4486 EL_CHAR('9'), -1, -1
4489 Xalpha_excla, TRUE, FALSE,
4490 EL_CHAR('!'), -1, -1
4493 Xalpha_quote, TRUE, FALSE,
4494 EL_CHAR('"'), -1, -1
4497 Xalpha_comma, TRUE, FALSE,
4498 EL_CHAR(','), -1, -1
4501 Xalpha_minus, TRUE, FALSE,
4502 EL_CHAR('-'), -1, -1
4505 Xalpha_perio, TRUE, FALSE,
4506 EL_CHAR('.'), -1, -1
4509 Xalpha_colon, TRUE, FALSE,
4510 EL_CHAR(':'), -1, -1
4513 Xalpha_quest, TRUE, FALSE,
4514 EL_CHAR('?'), -1, -1
4517 Xalpha_a, TRUE, FALSE,
4518 EL_CHAR('A'), -1, -1
4521 Xalpha_b, TRUE, FALSE,
4522 EL_CHAR('B'), -1, -1
4525 Xalpha_c, TRUE, FALSE,
4526 EL_CHAR('C'), -1, -1
4529 Xalpha_d, TRUE, FALSE,
4530 EL_CHAR('D'), -1, -1
4533 Xalpha_e, TRUE, FALSE,
4534 EL_CHAR('E'), -1, -1
4537 Xalpha_f, TRUE, FALSE,
4538 EL_CHAR('F'), -1, -1
4541 Xalpha_g, TRUE, FALSE,
4542 EL_CHAR('G'), -1, -1
4545 Xalpha_h, TRUE, FALSE,
4546 EL_CHAR('H'), -1, -1
4549 Xalpha_i, TRUE, FALSE,
4550 EL_CHAR('I'), -1, -1
4553 Xalpha_j, TRUE, FALSE,
4554 EL_CHAR('J'), -1, -1
4557 Xalpha_k, TRUE, FALSE,
4558 EL_CHAR('K'), -1, -1
4561 Xalpha_l, TRUE, FALSE,
4562 EL_CHAR('L'), -1, -1
4565 Xalpha_m, TRUE, FALSE,
4566 EL_CHAR('M'), -1, -1
4569 Xalpha_n, TRUE, FALSE,
4570 EL_CHAR('N'), -1, -1
4573 Xalpha_o, TRUE, FALSE,
4574 EL_CHAR('O'), -1, -1
4577 Xalpha_p, TRUE, FALSE,
4578 EL_CHAR('P'), -1, -1
4581 Xalpha_q, TRUE, FALSE,
4582 EL_CHAR('Q'), -1, -1
4585 Xalpha_r, TRUE, FALSE,
4586 EL_CHAR('R'), -1, -1
4589 Xalpha_s, TRUE, FALSE,
4590 EL_CHAR('S'), -1, -1
4593 Xalpha_t, TRUE, FALSE,
4594 EL_CHAR('T'), -1, -1
4597 Xalpha_u, TRUE, FALSE,
4598 EL_CHAR('U'), -1, -1
4601 Xalpha_v, TRUE, FALSE,
4602 EL_CHAR('V'), -1, -1
4605 Xalpha_w, TRUE, FALSE,
4606 EL_CHAR('W'), -1, -1
4609 Xalpha_x, TRUE, FALSE,
4610 EL_CHAR('X'), -1, -1
4613 Xalpha_y, TRUE, FALSE,
4614 EL_CHAR('Y'), -1, -1
4617 Xalpha_z, TRUE, FALSE,
4618 EL_CHAR('Z'), -1, -1
4621 Xalpha_arrow_e, TRUE, FALSE,
4622 EL_CHAR('>'), -1, -1
4625 Xalpha_arrow_w, TRUE, FALSE,
4626 EL_CHAR('<'), -1, -1
4629 Xalpha_copyr, TRUE, FALSE,
4630 EL_CHAR('©'), -1, -1
4633 Xalpha_copyr, TRUE, FALSE,
4634 EL_CHAR('©'), -1, -1
4638 Xboom_bug, FALSE, FALSE,
4639 EL_BUG, ACTION_EXPLODING, -1
4642 Xboom_bomb, FALSE, FALSE,
4643 EL_BOMB, ACTION_EXPLODING, -1
4646 Xboom_android, FALSE, FALSE,
4647 EL_EMC_ANDROID, ACTION_OTHER, -1
4650 Xboom_1, FALSE, FALSE,
4651 EL_DEFAULT, ACTION_EXPLODING, -1
4654 Xboom_2, FALSE, FALSE,
4655 EL_DEFAULT, ACTION_EXPLODING, -1
4658 Znormal, FALSE, FALSE,
4662 Zdynamite, FALSE, FALSE,
4666 Zplayer, FALSE, FALSE,
4670 ZBORDER, FALSE, FALSE,
4680 static struct Mapping_EM_to_RND_player
4689 em_player_mapping_list[] =
4693 EL_PLAYER_1, ACTION_MOVING, MV_BIT_UP,
4697 EL_PLAYER_1, ACTION_MOVING, MV_BIT_RIGHT,
4701 EL_PLAYER_1, ACTION_MOVING, MV_BIT_DOWN,
4705 EL_PLAYER_1, ACTION_MOVING, MV_BIT_LEFT,
4709 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_UP,
4713 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_RIGHT,
4717 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_DOWN,
4721 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_LEFT,
4725 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_UP,
4729 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_RIGHT,
4733 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_DOWN,
4737 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_LEFT,
4741 EL_PLAYER_2, ACTION_MOVING, MV_BIT_UP,
4745 EL_PLAYER_2, ACTION_MOVING, MV_BIT_RIGHT,
4749 EL_PLAYER_2, ACTION_MOVING, MV_BIT_DOWN,
4753 EL_PLAYER_2, ACTION_MOVING, MV_BIT_LEFT,
4757 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_UP,
4761 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_RIGHT,
4765 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_DOWN,
4769 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_LEFT,
4773 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_UP,
4777 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_RIGHT,
4781 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_DOWN,
4785 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_LEFT,
4789 EL_PLAYER_1, ACTION_DEFAULT, -1,
4793 EL_PLAYER_2, ACTION_DEFAULT, -1,
4802 int map_element_RND_to_EM(int element_rnd)
4804 static unsigned short mapping_RND_to_EM[NUM_FILE_ELEMENTS];
4805 static boolean mapping_initialized = FALSE;
4807 if (!mapping_initialized)
4811 /* return "Xalpha_quest" for all undefined elements in mapping array */
4812 for (i = 0; i < NUM_FILE_ELEMENTS; i++)
4813 mapping_RND_to_EM[i] = Xalpha_quest;
4815 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
4816 if (em_object_mapping_list[i].is_rnd_to_em_mapping)
4817 mapping_RND_to_EM[em_object_mapping_list[i].element_rnd] =
4818 em_object_mapping_list[i].element_em;
4820 mapping_initialized = TRUE;
4823 if (element_rnd >= 0 && element_rnd < NUM_FILE_ELEMENTS)
4824 return mapping_RND_to_EM[element_rnd];
4826 Error(ERR_WARN, "invalid RND level element %d", element_rnd);
4831 int map_element_EM_to_RND(int element_em)
4833 static unsigned short mapping_EM_to_RND[TILE_MAX];
4834 static boolean mapping_initialized = FALSE;
4836 if (!mapping_initialized)
4840 /* return "EL_UNKNOWN" for all undefined elements in mapping array */
4841 for (i = 0; i < TILE_MAX; i++)
4842 mapping_EM_to_RND[i] = EL_UNKNOWN;
4844 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
4845 mapping_EM_to_RND[em_object_mapping_list[i].element_em] =
4846 em_object_mapping_list[i].element_rnd;
4848 mapping_initialized = TRUE;
4851 if (element_em >= 0 && element_em < TILE_MAX)
4852 return mapping_EM_to_RND[element_em];
4854 Error(ERR_WARN, "invalid EM level element %d", element_em);
4861 int map_element_RND_to_EM(int element_rnd)
4863 static unsigned short mapping_RND_to_EM[NUM_FILE_ELEMENTS];
4864 static boolean mapping_initialized = FALSE;
4871 mapping_RND_to_EM_list[] =
4873 { Xblank, EL_EMPTY },
4874 { Xstone, EL_ROCK },
4876 { Xbug_n, EL_BUG_UP },
4877 { Xbug_e, EL_BUG_RIGHT },
4878 { Xbug_s, EL_BUG_DOWN },
4879 { Xbug_w, EL_BUG_LEFT },
4880 { Xtank_n, EL_SPACESHIP_UP },
4881 { Xtank_e, EL_SPACESHIP_RIGHT },
4882 { Xtank_s, EL_SPACESHIP_DOWN },
4883 { Xtank_w, EL_SPACESHIP_LEFT },
4884 { Xandroid, EL_EMC_ANDROID },
4885 { Xandroid_1_n, EL_EMC_ANDROID_UP },
4886 { Xandroid_1_e, EL_EMC_ANDROID_RIGHT },
4887 { Xandroid_1_w, EL_EMC_ANDROID_LEFT },
4888 { Xandroid_1_s, EL_EMC_ANDROID_DOWN },
4889 { Xspring, EL_SPRING },
4890 { Xeater_n, EL_YAMYAM },
4891 { Xalien, EL_ROBOT },
4892 { Xemerald, EL_EMERALD },
4893 { Xdiamond, EL_DIAMOND },
4894 { Xdrip_fall, EL_AMOEBA_DROP },
4896 { Xballoon, EL_BALLOON },
4897 { Xgrass, EL_EMC_GRASS },
4899 { Xacid_ne, EL_ACID_POOL_TOPRIGHT },
4900 { Xacid_se, EL_ACID_POOL_BOTTOMRIGHT },
4901 { Xacid_s, EL_ACID_POOL_BOTTOM },
4902 { Xacid_sw, EL_ACID_POOL_BOTTOMLEFT },
4903 { Xacid_nw, EL_ACID_POOL_TOPLEFT },
4904 { Xacid_1, EL_ACID },
4905 { Xball_1, EL_EMC_MAGIC_BALL },
4906 { Xgrow_ns, EL_EMC_GROW },
4907 { Xwonderwall, EL_MAGIC_WALL },
4908 { Xamoeba_1, EL_AMOEBA_WET },
4909 { Xdoor_1, EL_EM_GATE_1 },
4910 { Xdoor_2, EL_EM_GATE_2 },
4911 { Xdoor_3, EL_EM_GATE_3 },
4912 { Xdoor_4, EL_EM_GATE_4 },
4913 { Xdoor_5, EL_EMC_GATE_5 },
4914 { Xdoor_6, EL_EMC_GATE_6 },
4915 { Xdoor_7, EL_EMC_GATE_7 },
4916 { Xdoor_8, EL_EMC_GATE_8 },
4917 { Xkey_1, EL_EM_KEY_1 },
4918 { Xkey_2, EL_EM_KEY_2 },
4919 { Xkey_3, EL_EM_KEY_3 },
4920 { Xkey_4, EL_EM_KEY_4 },
4921 { Xkey_5, EL_EMC_KEY_5 },
4922 { Xkey_6, EL_EMC_KEY_6 },
4923 { Xkey_7, EL_EMC_KEY_7 },
4924 { Xkey_8, EL_EMC_KEY_8 },
4925 { Xwind_n, EL_BALLOON_SWITCH_UP },
4926 { Xwind_e, EL_BALLOON_SWITCH_RIGHT },
4927 { Xwind_s, EL_BALLOON_SWITCH_DOWN },
4928 { Xwind_w, EL_BALLOON_SWITCH_LEFT },
4929 { Xwind_nesw, EL_BALLOON_SWITCH_ANY },
4930 { Xwind_stop, EL_BALLOON_SWITCH_NONE },
4931 { Xexit, EL_EXIT_CLOSED },
4932 { Xexit_1, EL_EXIT_OPEN },
4933 { Xdynamite, EL_DYNAMITE },
4934 { Xdynamite_1, EL_DYNAMITE_ACTIVE },
4935 { Xbumper, EL_EMC_BUMPER },
4936 { Xwheel, EL_ROBOT_WHEEL },
4937 { Xswitch, EL_UNKNOWN },
4938 { Xsand, EL_QUICKSAND_EMPTY },
4939 { Xsand_stone, EL_QUICKSAND_FULL },
4940 { Xplant, EL_EMC_PLANT },
4941 { Xlenses, EL_EMC_LENSES },
4942 { Xmagnify, EL_EMC_MAGNIFIER },
4943 { Xdripper, EL_UNKNOWN },
4944 { Xfake_blank, EL_INVISIBLE_WALL },
4945 { Xfake_grass, EL_INVISIBLE_SAND },
4946 { Xfake_door_1, EL_EM_GATE_1_GRAY },
4947 { Xfake_door_2, EL_EM_GATE_2_GRAY },
4948 { Xfake_door_3, EL_EM_GATE_3_GRAY },
4949 { Xfake_door_4, EL_EM_GATE_4_GRAY },
4950 { Xfake_door_5, EL_EMC_GATE_5_GRAY },
4951 { Xfake_door_6, EL_EMC_GATE_6_GRAY },
4952 { Xfake_door_7, EL_EMC_GATE_7_GRAY },
4953 { Xfake_door_8, EL_EMC_GATE_8_GRAY },
4954 { Xsteel_1, EL_STEELWALL },
4955 { Xsteel_2, EL_UNKNOWN },
4956 { Xsteel_3, EL_EMC_STEELWALL_1 },
4957 { Xsteel_4, EL_UNKNOWN },
4958 { Xwall_1, EL_WALL },
4959 { Xwall_2, EL_UNKNOWN },
4960 { Xwall_3, EL_UNKNOWN },
4961 { Xwall_4, EL_UNKNOWN },
4962 { Xround_wall_1, EL_WALL_SLIPPERY },
4963 { Xround_wall_2, EL_UNKNOWN },
4964 { Xround_wall_3, EL_UNKNOWN },
4965 { Xround_wall_4, EL_UNKNOWN },
4966 { Xdecor_1, EL_UNKNOWN },
4967 { Xdecor_2, EL_EMC_WALL_6 },
4968 { Xdecor_3, EL_EMC_WALL_4 },
4969 { Xdecor_4, EL_EMC_WALL_5 },
4970 { Xdecor_5, EL_EMC_WALL_7 },
4971 { Xdecor_6, EL_EMC_WALL_8 },
4972 { Xdecor_7, EL_UNKNOWN },
4973 { Xdecor_8, EL_EMC_WALL_1 },
4974 { Xdecor_9, EL_EMC_WALL_2 },
4975 { Xdecor_10, EL_EMC_WALL_3 },
4976 { Xdecor_11, EL_UNKNOWN },
4977 { Xdecor_12, EL_UNKNOWN },
4978 { Xalpha_0, EL_CHAR('0') },
4979 { Xalpha_1, EL_CHAR('1') },
4980 { Xalpha_2, EL_CHAR('2') },
4981 { Xalpha_3, EL_CHAR('3') },
4982 { Xalpha_4, EL_CHAR('4') },
4983 { Xalpha_5, EL_CHAR('5') },
4984 { Xalpha_6, EL_CHAR('6') },
4985 { Xalpha_7, EL_CHAR('7') },
4986 { Xalpha_8, EL_CHAR('8') },
4987 { Xalpha_9, EL_CHAR('9') },
4988 { Xalpha_excla, EL_CHAR('!') },
4989 { Xalpha_quote, EL_CHAR('"') },
4990 { Xalpha_comma, EL_CHAR(',') },
4991 { Xalpha_minus, EL_CHAR('-') },
4992 { Xalpha_perio, EL_CHAR('.') },
4993 { Xalpha_colon, EL_CHAR(':') },
4994 { Xalpha_quest, EL_CHAR('?') },
4995 { Xalpha_a, EL_CHAR('A') },
4996 { Xalpha_b, EL_CHAR('B') },
4997 { Xalpha_c, EL_CHAR('C') },
4998 { Xalpha_d, EL_CHAR('D') },
4999 { Xalpha_e, EL_CHAR('E') },
5000 { Xalpha_f, EL_CHAR('F') },
5001 { Xalpha_g, EL_CHAR('G') },
5002 { Xalpha_h, EL_CHAR('H') },
5003 { Xalpha_i, EL_CHAR('I') },
5004 { Xalpha_j, EL_CHAR('J') },
5005 { Xalpha_k, EL_CHAR('K') },
5006 { Xalpha_l, EL_CHAR('L') },
5007 { Xalpha_m, EL_CHAR('M') },
5008 { Xalpha_n, EL_CHAR('N') },
5009 { Xalpha_o, EL_CHAR('O') },
5010 { Xalpha_p, EL_CHAR('P') },
5011 { Xalpha_q, EL_CHAR('Q') },
5012 { Xalpha_r, EL_CHAR('R') },
5013 { Xalpha_s, EL_CHAR('S') },
5014 { Xalpha_t, EL_CHAR('T') },
5015 { Xalpha_u, EL_CHAR('U') },
5016 { Xalpha_v, EL_CHAR('V') },
5017 { Xalpha_w, EL_CHAR('W') },
5018 { Xalpha_x, EL_CHAR('X') },
5019 { Xalpha_y, EL_CHAR('Y') },
5020 { Xalpha_z, EL_CHAR('Z') },
5021 { Xalpha_arrow_e, EL_CHAR('>') },
5022 { Xalpha_arrow_w, EL_CHAR('<') },
5023 { Xalpha_copyr, EL_CHAR('©') },
5025 { Zplayer, EL_PLAYER_1 },
5026 { Zplayer, EL_PLAYER_2 },
5027 { Zplayer, EL_PLAYER_3 },
5028 { Zplayer, EL_PLAYER_4 },
5030 { ZBORDER, EL_EMC_LEVEL_BORDER },
5035 if (!mapping_initialized)
5039 /* return "Xalpha_quest" for all undefined elements in mapping array */
5040 for (i = 0; i < NUM_FILE_ELEMENTS; i++)
5041 mapping_RND_to_EM[i] = Xalpha_quest;
5043 for (i = 0; mapping_RND_to_EM_list[i].element_rnd != -1; i++)
5044 mapping_RND_to_EM[mapping_RND_to_EM_list[i].element_rnd] =
5045 mapping_RND_to_EM_list[i].element_em;
5047 mapping_initialized = TRUE;
5050 if (element_rnd >= 0 && element_rnd < NUM_FILE_ELEMENTS)
5051 return mapping_RND_to_EM[element_rnd];
5053 Error(ERR_WARN, "invalid RND level element %d", element_rnd);
5058 int map_element_EM_to_RND(int element_em)
5060 static unsigned short mapping_EM_to_RND[TILE_MAX];
5061 static boolean mapping_initialized = FALSE;
5068 em_object_mapping_list[] =
5070 { Xblank, EL_EMPTY },
5071 { Yacid_splash_eB, EL_EMPTY },
5072 { Yacid_splash_wB, EL_EMPTY },
5074 #ifdef EM_ENGINE_BAD_ROLL
5075 { Xstone_force_e, EL_ROCK },
5076 { Xstone_force_w, EL_ROCK },
5077 { Xnut_force_e, EL_NUT },
5078 { Xnut_force_w, EL_NUT },
5079 { Xspring_force_e, EL_SPRING },
5080 { Xspring_force_w, EL_SPRING },
5081 { Xemerald_force_e, EL_EMERALD },
5082 { Xemerald_force_w, EL_EMERALD },
5083 { Xdiamond_force_e, EL_DIAMOND },
5084 { Xdiamond_force_w, EL_DIAMOND },
5085 { Xbomb_force_e, EL_BOMB },
5086 { Xbomb_force_w, EL_BOMB },
5089 { Xstone, EL_ROCK },
5090 { Xstone_pause, EL_ROCK },
5091 { Xstone_fall, EL_ROCK },
5092 { Ystone_s, EL_ROCK },
5093 { Ystone_sB, EL_ROCK },
5094 { Ystone_e, EL_ROCK },
5095 { Ystone_eB, EL_ROCK },
5096 { Ystone_w, EL_ROCK },
5097 { Ystone_wB, EL_ROCK },
5099 { Xnut_pause, EL_NUT },
5100 { Xnut_fall, EL_NUT },
5102 { Ynut_sB, EL_NUT },
5104 { Ynut_eB, EL_NUT },
5106 { Ynut_wB, EL_NUT },
5107 { Xbug_n, EL_BUG_UP },
5108 { Xbug_e, EL_BUG_RIGHT },
5109 { Xbug_s, EL_BUG_DOWN },
5110 { Xbug_w, EL_BUG_LEFT },
5111 { Xbug_gon, EL_BUG_UP },
5112 { Xbug_goe, EL_BUG_RIGHT },
5113 { Xbug_gos, EL_BUG_DOWN },
5114 { Xbug_gow, EL_BUG_LEFT },
5115 { Ybug_n, EL_BUG_UP },
5116 { Ybug_nB, EL_BUG_UP },
5117 { Ybug_e, EL_BUG_RIGHT },
5118 { Ybug_eB, EL_BUG_RIGHT },
5119 { Ybug_s, EL_BUG_DOWN },
5120 { Ybug_sB, EL_BUG_DOWN },
5121 { Ybug_w, EL_BUG_LEFT },
5122 { Ybug_wB, EL_BUG_LEFT },
5123 { Ybug_w_n, EL_BUG_UP },
5124 { Ybug_n_e, EL_BUG_RIGHT },
5125 { Ybug_e_s, EL_BUG_DOWN },
5126 { Ybug_s_w, EL_BUG_LEFT },
5127 { Ybug_e_n, EL_BUG_UP },
5128 { Ybug_s_e, EL_BUG_RIGHT },
5129 { Ybug_w_s, EL_BUG_DOWN },
5130 { Ybug_n_w, EL_BUG_LEFT },
5131 { Ybug_stone, EL_ROCK },
5132 { Ybug_spring, EL_SPRING },
5133 { Xtank_n, EL_SPACESHIP_UP },
5134 { Xtank_e, EL_SPACESHIP_RIGHT },
5135 { Xtank_s, EL_SPACESHIP_DOWN },
5136 { Xtank_w, EL_SPACESHIP_LEFT },
5137 { Xtank_gon, EL_SPACESHIP_UP },
5138 { Xtank_goe, EL_SPACESHIP_RIGHT },
5139 { Xtank_gos, EL_SPACESHIP_DOWN },
5140 { Xtank_gow, EL_SPACESHIP_LEFT },
5141 { Ytank_n, EL_SPACESHIP_UP },
5142 { Ytank_nB, EL_SPACESHIP_UP },
5143 { Ytank_e, EL_SPACESHIP_RIGHT },
5144 { Ytank_eB, EL_SPACESHIP_RIGHT },
5145 { Ytank_s, EL_SPACESHIP_DOWN },
5146 { Ytank_sB, EL_SPACESHIP_DOWN },
5147 { Ytank_w, EL_SPACESHIP_LEFT },
5148 { Ytank_wB, EL_SPACESHIP_LEFT },
5149 { Ytank_w_n, EL_SPACESHIP_UP },
5150 { Ytank_n_e, EL_SPACESHIP_RIGHT },
5151 { Ytank_e_s, EL_SPACESHIP_DOWN },
5152 { Ytank_s_w, EL_SPACESHIP_LEFT },
5153 { Ytank_e_n, EL_SPACESHIP_UP },
5154 { Ytank_s_e, EL_SPACESHIP_RIGHT },
5155 { Ytank_w_s, EL_SPACESHIP_DOWN },
5156 { Ytank_n_w, EL_SPACESHIP_LEFT },
5157 { Ytank_stone, EL_ROCK },
5158 { Ytank_spring, EL_SPRING },
5159 { Xandroid, EL_EMC_ANDROID },
5160 { Xandroid_1_n, EL_EMC_ANDROID_UP },
5161 { Xandroid_2_n, EL_EMC_ANDROID_UP },
5162 { Xandroid_1_e, EL_EMC_ANDROID_RIGHT },
5163 { Xandroid_2_e, EL_EMC_ANDROID_RIGHT },
5164 { Xandroid_1_w, EL_EMC_ANDROID_LEFT },
5165 { Xandroid_2_w, EL_EMC_ANDROID_LEFT },
5166 { Xandroid_1_s, EL_EMC_ANDROID_DOWN },
5167 { Xandroid_2_s, EL_EMC_ANDROID_DOWN },
5168 { Yandroid_n, EL_EMC_ANDROID_UP },
5169 { Yandroid_nB, EL_EMC_ANDROID_UP },
5170 { Yandroid_ne, EL_EMC_ANDROID_RIGHT_UP },
5171 { Yandroid_neB, EL_EMC_ANDROID_RIGHT_UP },
5172 { Yandroid_e, EL_EMC_ANDROID_RIGHT },
5173 { Yandroid_eB, EL_EMC_ANDROID_RIGHT },
5174 { Yandroid_se, EL_EMC_ANDROID_RIGHT_DOWN },
5175 { Yandroid_seB, EL_EMC_ANDROID_RIGHT_DOWN },
5176 { Yandroid_s, EL_EMC_ANDROID_DOWN },
5177 { Yandroid_sB, EL_EMC_ANDROID_DOWN },
5178 { Yandroid_sw, EL_EMC_ANDROID_LEFT_DOWN },
5179 { Yandroid_swB, EL_EMC_ANDROID_LEFT_DOWN },
5180 { Yandroid_w, EL_EMC_ANDROID_LEFT },
5181 { Yandroid_wB, EL_EMC_ANDROID_LEFT },
5182 { Yandroid_nw, EL_EMC_ANDROID_LEFT_UP },
5183 { Yandroid_nwB, EL_EMC_ANDROID_LEFT_UP },
5184 { Xspring, EL_SPRING },
5185 { Xspring_pause, EL_SPRING },
5186 { Xspring_e, EL_SPRING },
5187 { Xspring_w, EL_SPRING },
5188 { Xspring_fall, EL_SPRING },
5189 { Yspring_s, EL_SPRING },
5190 { Yspring_sB, EL_SPRING },
5191 { Yspring_e, EL_SPRING },
5192 { Yspring_eB, EL_SPRING },
5193 { Yspring_w, EL_SPRING },
5194 { Yspring_wB, EL_SPRING },
5195 { Yspring_kill_e, EL_SPRING },
5196 { Yspring_kill_eB, EL_SPRING },
5197 { Yspring_kill_w, EL_SPRING },
5198 { Yspring_kill_wB, EL_SPRING },
5199 { Xeater_n, EL_YAMYAM },
5200 { Xeater_e, EL_YAMYAM },
5201 { Xeater_w, EL_YAMYAM },
5202 { Xeater_s, EL_YAMYAM },
5203 { Yeater_n, EL_YAMYAM },
5204 { Yeater_nB, EL_YAMYAM },
5205 { Yeater_e, EL_YAMYAM },
5206 { Yeater_eB, EL_YAMYAM },
5207 { Yeater_s, EL_YAMYAM },
5208 { Yeater_sB, EL_YAMYAM },
5209 { Yeater_w, EL_YAMYAM },
5210 { Yeater_wB, EL_YAMYAM },
5211 { Yeater_stone, EL_ROCK },
5212 { Yeater_spring, EL_SPRING },
5213 { Xalien, EL_ROBOT },
5214 { Xalien_pause, EL_ROBOT },
5215 { Yalien_n, EL_ROBOT },
5216 { Yalien_nB, EL_ROBOT },
5217 { Yalien_e, EL_ROBOT },
5218 { Yalien_eB, EL_ROBOT },
5219 { Yalien_s, EL_ROBOT },
5220 { Yalien_sB, EL_ROBOT },
5221 { Yalien_w, EL_ROBOT },
5222 { Yalien_wB, EL_ROBOT },
5223 { Yalien_stone, EL_ROCK },
5224 { Yalien_spring, EL_SPRING },
5225 { Xemerald, EL_EMERALD },
5226 { Xemerald_pause, EL_EMERALD },
5227 { Xemerald_fall, EL_EMERALD },
5228 { Xemerald_shine, EL_EMERALD },
5229 { Yemerald_s, EL_EMERALD },
5230 { Yemerald_sB, EL_EMERALD },
5231 { Yemerald_e, EL_EMERALD },
5232 { Yemerald_eB, EL_EMERALD },
5233 { Yemerald_w, EL_EMERALD },
5234 { Yemerald_wB, EL_EMERALD },
5235 { Yemerald_eat, EL_EMERALD },
5236 { Yemerald_stone, EL_ROCK },
5237 { Xdiamond, EL_DIAMOND },
5238 { Xdiamond_pause, EL_DIAMOND },
5239 { Xdiamond_fall, EL_DIAMOND },
5240 { Xdiamond_shine, EL_DIAMOND },
5241 { Ydiamond_s, EL_DIAMOND },
5242 { Ydiamond_sB, EL_DIAMOND },
5243 { Ydiamond_e, EL_DIAMOND },
5244 { Ydiamond_eB, EL_DIAMOND },
5245 { Ydiamond_w, EL_DIAMOND },
5246 { Ydiamond_wB, EL_DIAMOND },
5247 { Ydiamond_eat, EL_DIAMOND },
5248 { Ydiamond_stone, EL_ROCK },
5249 { Xdrip_fall, EL_AMOEBA_DROP },
5250 { Xdrip_stretch, EL_AMOEBA_DROP },
5251 { Xdrip_stretchB, EL_AMOEBA_DROP },
5252 { Xdrip_eat, EL_AMOEBA_DROP },
5253 { Ydrip_s1, EL_AMOEBA_DROP },
5254 { Ydrip_s1B, EL_AMOEBA_DROP },
5255 { Ydrip_s2, EL_AMOEBA_DROP },
5256 { Ydrip_s2B, EL_AMOEBA_DROP },
5258 { Xbomb_pause, EL_BOMB },
5259 { Xbomb_fall, EL_BOMB },
5260 { Ybomb_s, EL_BOMB },
5261 { Ybomb_sB, EL_BOMB },
5262 { Ybomb_e, EL_BOMB },
5263 { Ybomb_eB, EL_BOMB },
5264 { Ybomb_w, EL_BOMB },
5265 { Ybomb_wB, EL_BOMB },
5266 { Ybomb_eat, EL_BOMB },
5267 { Xballoon, EL_BALLOON },
5268 { Yballoon_n, EL_BALLOON },
5269 { Yballoon_nB, EL_BALLOON },
5270 { Yballoon_e, EL_BALLOON },
5271 { Yballoon_eB, EL_BALLOON },
5272 { Yballoon_s, EL_BALLOON },
5273 { Yballoon_sB, EL_BALLOON },
5274 { Yballoon_w, EL_BALLOON },
5275 { Yballoon_wB, EL_BALLOON },
5276 { Xgrass, EL_SAND },
5277 { Ygrass_nB, EL_SAND },
5278 { Ygrass_eB, EL_SAND },
5279 { Ygrass_sB, EL_SAND },
5280 { Ygrass_wB, EL_SAND },
5282 { Ydirt_nB, EL_SAND },
5283 { Ydirt_eB, EL_SAND },
5284 { Ydirt_sB, EL_SAND },
5285 { Ydirt_wB, EL_SAND },
5286 { Xacid_ne, EL_ACID_POOL_TOPRIGHT },
5287 { Xacid_se, EL_ACID_POOL_BOTTOMRIGHT },
5288 { Xacid_s, EL_ACID_POOL_BOTTOM },
5289 { Xacid_sw, EL_ACID_POOL_BOTTOMLEFT },
5290 { Xacid_nw, EL_ACID_POOL_TOPLEFT },
5291 { Xacid_1, EL_ACID },
5292 { Xacid_2, EL_ACID },
5293 { Xacid_3, EL_ACID },
5294 { Xacid_4, EL_ACID },
5295 { Xacid_5, EL_ACID },
5296 { Xacid_6, EL_ACID },
5297 { Xacid_7, EL_ACID },
5298 { Xacid_8, EL_ACID },
5299 { Xball_1, EL_EMC_MAGIC_BALL },
5300 { Xball_1B, EL_EMC_MAGIC_BALL },
5301 { Xball_2, EL_EMC_MAGIC_BALL },
5302 { Xball_2B, EL_EMC_MAGIC_BALL },
5303 { Yball_eat, EL_EMC_MAGIC_BALL },
5304 { Xgrow_ns, EL_EMC_GROW },
5305 { Ygrow_ns_eat, EL_EMC_GROW },
5306 { Xgrow_ew, EL_EMC_GROW },
5307 { Ygrow_ew_eat, EL_EMC_GROW },
5308 { Xwonderwall, EL_MAGIC_WALL },
5309 { XwonderwallB, EL_MAGIC_WALL },
5310 { Xamoeba_1, EL_AMOEBA_WET },
5311 { Xamoeba_2, EL_AMOEBA_WET },
5312 { Xamoeba_3, EL_AMOEBA_WET },
5313 { Xamoeba_4, EL_AMOEBA_WET },
5314 { Xamoeba_5, EL_AMOEBA_WET },
5315 { Xamoeba_6, EL_AMOEBA_WET },
5316 { Xamoeba_7, EL_AMOEBA_WET },
5317 { Xamoeba_8, EL_AMOEBA_WET },
5318 { Xdoor_1, EL_EM_GATE_1 },
5319 { Xdoor_2, EL_EM_GATE_2 },
5320 { Xdoor_3, EL_EM_GATE_3 },
5321 { Xdoor_4, EL_EM_GATE_4 },
5322 { Xdoor_5, EL_EMC_GATE_5 },
5323 { Xdoor_6, EL_EMC_GATE_6 },
5324 { Xdoor_7, EL_EMC_GATE_7 },
5325 { Xdoor_8, EL_EMC_GATE_8 },
5326 { Xkey_1, EL_EM_KEY_1 },
5327 { Xkey_2, EL_EM_KEY_2 },
5328 { Xkey_3, EL_EM_KEY_3 },
5329 { Xkey_4, EL_EM_KEY_4 },
5330 { Xkey_5, EL_EMC_KEY_5 },
5331 { Xkey_6, EL_EMC_KEY_6 },
5332 { Xkey_7, EL_EMC_KEY_7 },
5333 { Xkey_8, EL_EMC_KEY_8 },
5334 { Xwind_n, EL_BALLOON_SWITCH_UP },
5335 { Xwind_e, EL_BALLOON_SWITCH_RIGHT },
5336 { Xwind_s, EL_BALLOON_SWITCH_DOWN },
5337 { Xwind_w, EL_BALLOON_SWITCH_LEFT },
5338 { Xwind_nesw, EL_BALLOON_SWITCH_ANY },
5339 { Xwind_stop, EL_BALLOON_SWITCH_NONE },
5340 { Xexit, EL_EXIT_CLOSED },
5341 { Xexit_1, EL_EXIT_OPEN },
5342 { Xexit_2, EL_EXIT_OPEN },
5343 { Xexit_3, EL_EXIT_OPEN },
5344 { Xdynamite, EL_DYNAMITE },
5345 { Ydynamite_eat, EL_DYNAMITE },
5346 { Xdynamite_1, EL_DYNAMITE_ACTIVE },
5347 { Xdynamite_2, EL_DYNAMITE_ACTIVE },
5348 { Xdynamite_3, EL_DYNAMITE_ACTIVE },
5349 { Xdynamite_4, EL_DYNAMITE_ACTIVE },
5350 { Xbumper, EL_EMC_BUMPER },
5351 { XbumperB, EL_EMC_BUMPER },
5352 { Xwheel, EL_ROBOT_WHEEL },
5353 { XwheelB, EL_ROBOT_WHEEL },
5354 { Xswitch, EL_UNKNOWN },
5355 { XswitchB, EL_UNKNOWN },
5356 { Xsand, EL_QUICKSAND_EMPTY },
5357 { Xsand_stone, EL_QUICKSAND_FULL },
5358 { Xsand_stonein_1, EL_QUICKSAND_FULL },
5359 { Xsand_stonein_2, EL_QUICKSAND_FULL },
5360 { Xsand_stonein_3, EL_QUICKSAND_FULL },
5361 { Xsand_stonein_4, EL_QUICKSAND_FULL },
5362 { Xsand_stonesand_1, EL_QUICKSAND_FULL },
5363 { Xsand_stonesand_2, EL_QUICKSAND_FULL },
5364 { Xsand_stonesand_3, EL_QUICKSAND_FULL },
5365 { Xsand_stonesand_4, EL_QUICKSAND_FULL },
5366 { Xsand_stoneout_1, EL_QUICKSAND_FULL },
5367 { Xsand_stoneout_2, EL_QUICKSAND_FULL },
5368 { Xsand_sandstone_1, EL_QUICKSAND_FULL },
5369 { Xsand_sandstone_2, EL_QUICKSAND_FULL },
5370 { Xsand_sandstone_3, EL_QUICKSAND_FULL },
5371 { Xsand_sandstone_4, EL_QUICKSAND_FULL },
5372 { Xplant, EL_EMC_PLANT },
5373 { Yplant, EL_EMC_PLANT },
5374 { Xlenses, EL_EMC_LENSES },
5375 { Xmagnify, EL_EMC_MAGNIFIER },
5376 { Xdripper, EL_UNKNOWN },
5377 { XdripperB, EL_UNKNOWN },
5378 { Xfake_blank, EL_INVISIBLE_WALL },
5379 { Xfake_blankB, EL_INVISIBLE_WALL },
5380 { Xfake_grass, EL_INVISIBLE_SAND },
5381 { Xfake_grassB, EL_INVISIBLE_SAND },
5382 { Xfake_door_1, EL_EM_GATE_1_GRAY },
5383 { Xfake_door_2, EL_EM_GATE_2_GRAY },
5384 { Xfake_door_3, EL_EM_GATE_3_GRAY },
5385 { Xfake_door_4, EL_EM_GATE_4_GRAY },
5386 { Xfake_door_5, EL_EMC_GATE_5_GRAY },
5387 { Xfake_door_6, EL_EMC_GATE_6_GRAY },
5388 { Xfake_door_7, EL_EMC_GATE_7_GRAY },
5389 { Xfake_door_8, EL_EMC_GATE_8_GRAY },
5390 { Xsteel_1, EL_STEELWALL },
5391 { Xsteel_2, EL_UNKNOWN },
5392 { Xsteel_3, EL_EMC_STEELWALL_1 },
5393 { Xsteel_4, EL_UNKNOWN },
5394 { Xwall_1, EL_WALL },
5395 { Xwall_2, EL_UNKNOWN },
5396 { Xwall_3, EL_UNKNOWN },
5397 { Xwall_4, EL_UNKNOWN },
5398 { Xround_wall_1, EL_WALL_SLIPPERY },
5399 { Xround_wall_2, EL_UNKNOWN },
5400 { Xround_wall_3, EL_UNKNOWN },
5401 { Xround_wall_4, EL_UNKNOWN },
5402 { Xdecor_1, EL_UNKNOWN },
5403 { Xdecor_2, EL_EMC_WALL_6 },
5404 { Xdecor_3, EL_EMC_WALL_4 },
5405 { Xdecor_4, EL_EMC_WALL_5 },
5406 { Xdecor_5, EL_EMC_WALL_7 },
5407 { Xdecor_6, EL_EMC_WALL_8 },
5408 { Xdecor_7, EL_UNKNOWN },
5409 { Xdecor_8, EL_EMC_WALL_1 },
5410 { Xdecor_9, EL_EMC_WALL_2 },
5411 { Xdecor_10, EL_EMC_WALL_3 },
5412 { Xdecor_11, EL_UNKNOWN },
5413 { Xdecor_12, EL_UNKNOWN },
5414 { Xalpha_0, EL_CHAR('0') },
5415 { Xalpha_1, EL_CHAR('1') },
5416 { Xalpha_2, EL_CHAR('2') },
5417 { Xalpha_3, EL_CHAR('3') },
5418 { Xalpha_4, EL_CHAR('4') },
5419 { Xalpha_5, EL_CHAR('5') },
5420 { Xalpha_6, EL_CHAR('6') },
5421 { Xalpha_7, EL_CHAR('7') },
5422 { Xalpha_8, EL_CHAR('8') },
5423 { Xalpha_9, EL_CHAR('9') },
5424 { Xalpha_excla, EL_CHAR('!') },
5425 { Xalpha_quote, EL_CHAR('"') },
5426 { Xalpha_comma, EL_CHAR(',') },
5427 { Xalpha_minus, EL_CHAR('-') },
5428 { Xalpha_perio, EL_CHAR('.') },
5429 { Xalpha_colon, EL_CHAR(':') },
5430 { Xalpha_quest, EL_CHAR('?') },
5431 { Xalpha_a, EL_CHAR('A') },
5432 { Xalpha_b, EL_CHAR('B') },
5433 { Xalpha_c, EL_CHAR('C') },
5434 { Xalpha_d, EL_CHAR('D') },
5435 { Xalpha_e, EL_CHAR('E') },
5436 { Xalpha_f, EL_CHAR('F') },
5437 { Xalpha_g, EL_CHAR('G') },
5438 { Xalpha_h, EL_CHAR('H') },
5439 { Xalpha_i, EL_CHAR('I') },
5440 { Xalpha_j, EL_CHAR('J') },
5441 { Xalpha_k, EL_CHAR('K') },
5442 { Xalpha_l, EL_CHAR('L') },
5443 { Xalpha_m, EL_CHAR('M') },
5444 { Xalpha_n, EL_CHAR('N') },
5445 { Xalpha_o, EL_CHAR('O') },
5446 { Xalpha_p, EL_CHAR('P') },
5447 { Xalpha_q, EL_CHAR('Q') },
5448 { Xalpha_r, EL_CHAR('R') },
5449 { Xalpha_s, EL_CHAR('S') },
5450 { Xalpha_t, EL_CHAR('T') },
5451 { Xalpha_u, EL_CHAR('U') },
5452 { Xalpha_v, EL_CHAR('V') },
5453 { Xalpha_w, EL_CHAR('W') },
5454 { Xalpha_x, EL_CHAR('X') },
5455 { Xalpha_y, EL_CHAR('Y') },
5456 { Xalpha_z, EL_CHAR('Z') },
5457 { Xalpha_arrow_e, EL_CHAR('>') },
5458 { Xalpha_arrow_w, EL_CHAR('<') },
5459 { Xalpha_copyr, EL_CHAR('©') },
5461 { Zplayer, EL_PLAYER_1 },
5463 { ZBORDER, EL_EMC_LEVEL_BORDER },
5468 if (!mapping_initialized)
5472 /* return "EL_UNKNOWN" for all undefined elements in mapping array */
5473 for (i = 0; i < TILE_MAX; i++)
5474 mapping_EM_to_RND[i] = EL_UNKNOWN;
5476 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
5477 mapping_EM_to_RND[em_object_mapping_list[i].element_em] =
5478 em_object_mapping_list[i].element_rnd;
5480 mapping_initialized = TRUE;
5483 if (element_em >= 0 && element_em < TILE_MAX)
5484 return mapping_EM_to_RND[element_em];
5486 Error(ERR_WARN, "invalid EM level element %d", element_em);
5493 int get_next_element(int element)
5497 case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL;
5498 case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY;
5499 case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL;
5500 case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_ACTIVE;
5501 case EL_BD_MAGIC_WALL_FILLING: return EL_BD_MAGIC_WALL_FULL;
5502 case EL_BD_MAGIC_WALL_EMPTYING: return EL_BD_MAGIC_WALL_ACTIVE;
5503 case EL_AMOEBA_DROPPING: return EL_AMOEBA_WET;
5505 default: return element;
5510 int el_act_dir2img(int element, int action, int direction)
5512 element = GFX_ELEMENT(element);
5514 if (direction == MV_NO_MOVING)
5515 return element_info[element].graphic[action];
5517 direction = MV_DIR_BIT(direction);
5519 return element_info[element].direction_graphic[action][direction];
5522 int el_act_dir2img(int element, int action, int direction)
5524 element = GFX_ELEMENT(element);
5525 direction = MV_DIR_BIT(direction); /* default: MV_NO_MOVING => MV_DOWN */
5527 /* direction_graphic[][] == graphic[] for undefined direction graphics */
5528 return element_info[element].direction_graphic[action][direction];
5533 static int el_act_dir2crm(int element, int action, int direction)
5535 element = GFX_ELEMENT(element);
5537 if (direction == MV_NO_MOVING)
5538 return element_info[element].crumbled[action];
5540 direction = MV_DIR_BIT(direction);
5542 return element_info[element].direction_crumbled[action][direction];
5545 static int el_act_dir2crm(int element, int action, int direction)
5547 element = GFX_ELEMENT(element);
5548 direction = MV_DIR_BIT(direction); /* default: MV_NO_MOVING => MV_DOWN */
5550 /* direction_graphic[][] == graphic[] for undefined direction graphics */
5551 return element_info[element].direction_crumbled[action][direction];
5555 int el_act2img(int element, int action)
5557 element = GFX_ELEMENT(element);
5559 return element_info[element].graphic[action];
5562 int el_act2crm(int element, int action)
5564 element = GFX_ELEMENT(element);
5566 return element_info[element].crumbled[action];
5569 int el_dir2img(int element, int direction)
5571 element = GFX_ELEMENT(element);
5573 return el_act_dir2img(element, ACTION_DEFAULT, direction);
5576 int el2baseimg(int element)
5578 return element_info[element].graphic[ACTION_DEFAULT];
5581 int el2img(int element)
5583 element = GFX_ELEMENT(element);
5585 return element_info[element].graphic[ACTION_DEFAULT];
5588 int el2edimg(int element)
5590 element = GFX_ELEMENT(element);
5592 return element_info[element].special_graphic[GFX_SPECIAL_ARG_EDITOR];
5595 int el2preimg(int element)
5597 element = GFX_ELEMENT(element);
5599 return element_info[element].special_graphic[GFX_SPECIAL_ARG_PREVIEW];
5602 int getGameFrameDelay_EM(int native_em_game_frame_delay)
5604 int game_frame_delay_value;
5606 game_frame_delay_value =
5607 (tape.playing && tape.fast_forward ? FfwdFrameDelay :
5608 GameFrameDelay == GAME_FRAME_DELAY ? native_em_game_frame_delay :
5611 if (tape.playing && tape.warp_forward && !tape.pausing)
5612 game_frame_delay_value = 0;
5614 return game_frame_delay_value;
5617 unsigned int InitRND(long seed)
5619 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
5620 return InitEngineRND_EM(seed);
5622 return InitEngineRND(seed);
5625 #define DEBUG_EM_GFX 0
5627 void InitGraphicInfo_EM(void)
5629 struct Mapping_EM_to_RND_object object_mapping[TILE_MAX];
5630 struct Mapping_EM_to_RND_player player_mapping[2][SPR_MAX];
5634 if (graphic_info_em_object[0][0].bitmap == NULL)
5636 /* EM graphics not yet initialized in em_open_all() */
5642 /* always start with reliable default values */
5643 for (i = 0; i < TILE_MAX; i++)
5645 object_mapping[i].element_rnd = EL_UNKNOWN;
5646 object_mapping[i].is_backside = FALSE;
5647 object_mapping[i].action = ACTION_DEFAULT;
5648 object_mapping[i].direction = MV_NO_MOVING;
5651 /* always start with reliable default values */
5652 for (p = 0; p < 2; p++)
5654 for (i = 0; i < SPR_MAX; i++)
5656 player_mapping[p][i].element_rnd = EL_UNKNOWN;
5657 player_mapping[p][i].action = ACTION_DEFAULT;
5658 player_mapping[p][i].direction = MV_NO_MOVING;
5662 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
5664 int e = em_object_mapping_list[i].element_em;
5666 object_mapping[e].element_rnd = em_object_mapping_list[i].element_rnd;
5667 object_mapping[e].is_backside = em_object_mapping_list[i].is_backside;
5669 if (em_object_mapping_list[i].action != -1)
5670 object_mapping[e].action = em_object_mapping_list[i].action;
5672 if (em_object_mapping_list[i].direction != -1)
5673 object_mapping[e].direction = (1 << em_object_mapping_list[i].direction);
5676 for (i = 0; em_player_mapping_list[i].action_em != -1; i++)
5678 int a = em_player_mapping_list[i].action_em;
5679 int p = em_player_mapping_list[i].player_nr;
5681 player_mapping[p][a].element_rnd = em_player_mapping_list[i].element_rnd;
5683 if (em_player_mapping_list[i].action != -1)
5684 player_mapping[p][a].action = em_player_mapping_list[i].action;
5686 if (em_player_mapping_list[i].direction != -1)
5687 player_mapping[p][a].direction =
5688 (1 << em_player_mapping_list[i].direction);
5691 for (i = 0; i < TILE_MAX; i++)
5693 int element = object_mapping[i].element_rnd;
5694 int action = object_mapping[i].action;
5695 int direction = object_mapping[i].direction;
5696 boolean is_backside = object_mapping[i].is_backside;
5697 boolean action_removing = (action == ACTION_DIGGING ||
5698 action == ACTION_SNAPPING ||
5699 action == ACTION_COLLECTING);
5700 boolean action_exploding = ((action == ACTION_EXPLODING ||
5701 action == ACTION_SMASHED_BY_ROCK ||
5702 action == ACTION_SMASHED_BY_SPRING) &&
5703 element != EL_DIAMOND);
5704 boolean action_active = (action == ACTION_ACTIVE);
5705 boolean action_other = (action == ACTION_OTHER);
5707 for (j = 0; j < 8; j++)
5709 int effective_element = (j > 5 && i == Yacid_splash_eB ? EL_EMPTY :
5710 j > 5 && i == Yacid_splash_wB ? EL_EMPTY :
5712 i == Xdrip_stretch ? element :
5713 i == Xdrip_stretchB ? element :
5714 i == Ydrip_s1 ? element :
5715 i == Ydrip_s1B ? element :
5716 i == Xball_1B ? element :
5717 i == Xball_2 ? element :
5718 i == Xball_2B ? element :
5719 i == Yball_eat ? element :
5720 i == Ykey_1_eat ? element :
5721 i == Ykey_2_eat ? element :
5722 i == Ykey_3_eat ? element :
5723 i == Ykey_4_eat ? element :
5724 i == Ykey_5_eat ? element :
5725 i == Ykey_6_eat ? element :
5726 i == Ykey_7_eat ? element :
5727 i == Ykey_8_eat ? element :
5728 i == Ylenses_eat ? element :
5729 i == Ymagnify_eat ? element :
5730 i == Ygrass_eat ? element :
5731 i == Ydirt_eat ? element :
5732 i == Yspring_kill_e ? EL_SPRING :
5733 i == Yspring_kill_w ? EL_SPRING :
5734 i == Yemerald_stone ? EL_EMERALD :
5735 i == Ydiamond_stone ? EL_ROCK :
5736 i == Xsand_stonein_4 ? EL_EMPTY :
5737 i == Xsand_stoneout_2 ? EL_ROCK :
5738 is_backside ? EL_EMPTY :
5739 action_removing ? EL_EMPTY :
5741 int effective_action = (j < 7 ? action :
5742 i == Xdrip_stretch ? action :
5743 i == Xdrip_stretchB ? action :
5744 i == Ydrip_s1 ? action :
5745 i == Ydrip_s1B ? action :
5746 i == Xball_1B ? action :
5747 i == Xball_2 ? action :
5748 i == Xball_2B ? action :
5749 i == Yball_eat ? action :
5750 i == Ykey_1_eat ? action :
5751 i == Ykey_2_eat ? action :
5752 i == Ykey_3_eat ? action :
5753 i == Ykey_4_eat ? action :
5754 i == Ykey_5_eat ? action :
5755 i == Ykey_6_eat ? action :
5756 i == Ykey_7_eat ? action :
5757 i == Ykey_8_eat ? action :
5758 i == Ylenses_eat ? action :
5759 i == Ymagnify_eat ? action :
5760 i == Ygrass_eat ? action :
5761 i == Ydirt_eat ? action :
5762 i == Xsand_stonein_1 ? action :
5763 i == Xsand_stonein_2 ? action :
5764 i == Xsand_stonein_3 ? action :
5765 i == Xsand_stonein_4 ? action :
5766 i == Xsand_stoneout_1 ? action :
5767 i == Xsand_stoneout_2 ? action :
5768 i == Xboom_android ? ACTION_EXPLODING :
5769 action_exploding ? ACTION_EXPLODING :
5770 action_active ? action :
5771 action_other ? action :
5773 int graphic = (el_act_dir2img(effective_element, effective_action,
5775 int crumbled = (el_act_dir2crm(effective_element, effective_action,
5777 int base_graphic = el_act2img(effective_element, ACTION_DEFAULT);
5778 int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT);
5779 boolean has_crumbled_graphics = (base_crumbled != base_graphic);
5780 struct GraphicInfo *g = &graphic_info[graphic];
5781 struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
5784 /* ensure to get symmetric 3-frame, 2-delay animations as used in EM */
5785 boolean special_animation = (action != ACTION_DEFAULT &&
5786 g->anim_frames == 3 &&
5787 g->anim_delay == 2 &&
5788 g->anim_mode & ANIM_LINEAR);
5789 int sync_frame = (i == Xdrip_stretch ? 7 :
5790 i == Xdrip_stretchB ? 7 :
5791 i == Ydrip_s2 ? j + 8 :
5792 i == Ydrip_s2B ? j + 8 :
5802 i == Xball_2B ? j + 8 :
5803 i == Yball_eat ? j + 1 :
5804 i == Ykey_1_eat ? j + 1 :
5805 i == Ykey_2_eat ? j + 1 :
5806 i == Ykey_3_eat ? j + 1 :
5807 i == Ykey_4_eat ? j + 1 :
5808 i == Ykey_5_eat ? j + 1 :
5809 i == Ykey_6_eat ? j + 1 :
5810 i == Ykey_7_eat ? j + 1 :
5811 i == Ykey_8_eat ? j + 1 :
5812 i == Ylenses_eat ? j + 1 :
5813 i == Ymagnify_eat ? j + 1 :
5814 i == Ygrass_eat ? j + 1 :
5815 i == Ydirt_eat ? j + 1 :
5816 i == Xamoeba_1 ? 0 :
5817 i == Xamoeba_2 ? 1 :
5818 i == Xamoeba_3 ? 2 :
5819 i == Xamoeba_4 ? 3 :
5820 i == Xamoeba_5 ? 0 :
5821 i == Xamoeba_6 ? 1 :
5822 i == Xamoeba_7 ? 2 :
5823 i == Xamoeba_8 ? 3 :
5824 i == Xexit_2 ? j + 8 :
5825 i == Xexit_3 ? j + 16 :
5826 i == Xdynamite_1 ? 0 :
5827 i == Xdynamite_2 ? 20 :
5828 i == Xdynamite_3 ? 40 :
5829 i == Xdynamite_4 ? 60 :
5830 i == Xsand_stonein_1 ? j + 1 :
5831 i == Xsand_stonein_2 ? j + 9 :
5832 i == Xsand_stonein_3 ? j + 17 :
5833 i == Xsand_stonein_4 ? j + 25 :
5834 i == Xsand_stoneout_1 && j == 0 ? 0 :
5835 i == Xsand_stoneout_1 && j == 1 ? 0 :
5836 i == Xsand_stoneout_1 && j == 2 ? 1 :
5837 i == Xsand_stoneout_1 && j == 3 ? 2 :
5838 i == Xsand_stoneout_1 && j == 4 ? 2 :
5839 i == Xsand_stoneout_1 && j == 5 ? 3 :
5840 i == Xsand_stoneout_1 && j == 6 ? 4 :
5841 i == Xsand_stoneout_1 && j == 7 ? 4 :
5842 i == Xsand_stoneout_2 && j == 0 ? 5 :
5843 i == Xsand_stoneout_2 && j == 1 ? 6 :
5844 i == Xsand_stoneout_2 && j == 2 ? 7 :
5845 i == Xsand_stoneout_2 && j == 3 ? 8 :
5846 i == Xsand_stoneout_2 && j == 4 ? 9 :
5847 i == Xsand_stoneout_2 && j == 5 ? 11 :
5848 i == Xsand_stoneout_2 && j == 6 ? 13 :
5849 i == Xsand_stoneout_2 && j == 7 ? 15 :
5850 i == Xboom_bug && j == 1 ? 2 :
5851 i == Xboom_bug && j == 2 ? 2 :
5852 i == Xboom_bug && j == 3 ? 4 :
5853 i == Xboom_bug && j == 4 ? 4 :
5854 i == Xboom_bug && j == 5 ? 2 :
5855 i == Xboom_bug && j == 6 ? 2 :
5856 i == Xboom_bug && j == 7 ? 0 :
5857 i == Xboom_bomb && j == 1 ? 2 :
5858 i == Xboom_bomb && j == 2 ? 2 :
5859 i == Xboom_bomb && j == 3 ? 4 :
5860 i == Xboom_bomb && j == 4 ? 4 :
5861 i == Xboom_bomb && j == 5 ? 2 :
5862 i == Xboom_bomb && j == 6 ? 2 :
5863 i == Xboom_bomb && j == 7 ? 0 :
5864 i == Xboom_android && j == 7 ? 6 :
5865 i == Xboom_1 && j == 1 ? 2 :
5866 i == Xboom_1 && j == 2 ? 2 :
5867 i == Xboom_1 && j == 3 ? 4 :
5868 i == Xboom_1 && j == 4 ? 4 :
5869 i == Xboom_1 && j == 5 ? 6 :
5870 i == Xboom_1 && j == 6 ? 6 :
5871 i == Xboom_1 && j == 7 ? 8 :
5872 i == Xboom_2 && j == 0 ? 8 :
5873 i == Xboom_2 && j == 1 ? 8 :
5874 i == Xboom_2 && j == 2 ? 10 :
5875 i == Xboom_2 && j == 3 ? 10 :
5876 i == Xboom_2 && j == 4 ? 10 :
5877 i == Xboom_2 && j == 5 ? 12 :
5878 i == Xboom_2 && j == 6 ? 12 :
5879 i == Xboom_2 && j == 7 ? 12 :
5880 special_animation && j == 4 ? 3 :
5881 effective_action != action ? 0 :
5885 Bitmap *debug_bitmap = g_em->bitmap;
5886 int debug_src_x = g_em->src_x;
5887 int debug_src_y = g_em->src_y;
5890 int frame = getAnimationFrame(g->anim_frames,
5893 g->anim_start_frame,
5896 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y,
5897 g->double_movement && is_backside);
5900 g_em->bitmap = src_bitmap;
5901 g_em->src_x = src_x;
5902 g_em->src_y = src_y;
5903 g_em->src_offset_x = 0;
5904 g_em->src_offset_y = 0;
5905 g_em->dst_offset_x = 0;
5906 g_em->dst_offset_y = 0;
5907 g_em->width = TILEX;
5908 g_em->height = TILEY;
5910 g_em->has_crumbled_graphics = FALSE;
5911 g_em->crumbled_bitmap = NULL;
5912 g_em->crumbled_src_x = 0;
5913 g_em->crumbled_src_y = 0;
5914 g_em->crumbled_border_size = 0;
5918 if (effective_element == EL_EMC_GRASS &&
5919 effective_action == ACTION_DIGGING)
5920 printf("::: %d\n", crumbled);
5924 if (has_crumbled_graphics && crumbled == IMG_EMPTY_SPACE)
5925 printf("::: empty crumbled: %d [%s], %d, %d\n",
5926 effective_element, element_info[effective_element].token_name,
5927 effective_action, direction);
5930 /* if element can be crumbled, but certain action graphics are just empty
5931 space (like snapping sand with the original R'n'D graphics), do not
5932 treat these empty space graphics as crumbled graphics in EMC engine */
5933 if (has_crumbled_graphics && crumbled != IMG_EMPTY_SPACE)
5935 getGraphicSource(crumbled, frame, &src_bitmap, &src_x, &src_y);
5937 g_em->has_crumbled_graphics = TRUE;
5938 g_em->crumbled_bitmap = src_bitmap;
5939 g_em->crumbled_src_x = src_x;
5940 g_em->crumbled_src_y = src_y;
5941 g_em->crumbled_border_size = graphic_info[crumbled].border_size;
5945 if (!g->double_movement && (effective_action == ACTION_FALLING ||
5946 effective_action == ACTION_MOVING ||
5947 effective_action == ACTION_PUSHING))
5950 (effective_action == ACTION_FALLING ? MV_DOWN : direction);
5951 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? 1 : 0);
5952 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? 1 : 0);
5953 int cx = ABS(dx) * TILEX / 8;
5954 int cy = ABS(dy) * TILEY / 8;
5956 if (is_backside) /* tile where movement starts */
5958 if (dx < 0 || dy < 0)
5960 g_em->src_offset_x = cx * (j + 1);
5961 g_em->src_offset_y = cy * (j + 1);
5965 g_em->dst_offset_x = cx * (j + 1);
5966 g_em->dst_offset_y = cy * (j + 1);
5969 g_em->width = TILEX - cx * (j + 1);
5970 g_em->height = TILEY - cy * (j + 1);
5972 else /* tile where movement ends */
5974 if (dx < 0 || dy < 0)
5976 g_em->dst_offset_x = cx * (7 - j);
5977 g_em->dst_offset_y = cy * (7 - j);
5981 g_em->src_offset_x = cx * (7 - j);
5982 g_em->src_offset_y = cy * (7 - j);
5985 g_em->width = TILEX - cx * (7 - j);
5986 g_em->height = TILEY - cy * (7 - j);
5991 /* create unique graphic identifier to decide if tile must be redrawn */
5992 /* bit 31 - 16 (16 bit): EM style element
5993 bit 15 - 12 ( 4 bit): EM style frame
5994 bit 11 - 6 ( 6 bit): graphic width
5995 bit 5 - 0 ( 6 bit): graphic height */
5996 g_em->unique_identifier =
5997 (i << 16) | (j << 12) | (g_em->width << 6) | g_em->height;
6000 if (g_em->bitmap != debug_bitmap ||
6001 g_em->src_x != debug_src_x ||
6002 g_em->src_y != debug_src_y ||
6003 g_em->src_offset_x != 0 ||
6004 g_em->src_offset_y != 0 ||
6005 g_em->dst_offset_x != 0 ||
6006 g_em->dst_offset_y != 0 ||
6007 g_em->width != TILEX ||
6008 g_em->height != TILEY)
6010 static int last_i = -1;
6018 printf("::: EMC GFX ERROR for element %d -> %d ('%s', '%s', %d)",
6019 i, element, element_info[element].token_name,
6020 element_action_info[effective_action].suffix, direction);
6022 if (element != effective_element)
6023 printf(" [%d ('%s')]",
6025 element_info[effective_element].token_name);
6029 if (g_em->bitmap != debug_bitmap)
6030 printf(" %d (%d): different bitmap! (0x%08x != 0x%08x)\n",
6031 j, is_backside, (int)(g_em->bitmap), (int)(debug_bitmap));
6033 if (g_em->src_x != debug_src_x ||
6034 g_em->src_y != debug_src_y)
6035 printf(" frame %d (%c): %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
6036 j, (is_backside ? 'B' : 'F'),
6037 g_em->src_x, g_em->src_y,
6038 g_em->src_x / 32, g_em->src_y / 32,
6039 debug_src_x, debug_src_y,
6040 debug_src_x / 32, debug_src_y / 32);
6042 if (g_em->src_offset_x != 0 ||
6043 g_em->src_offset_y != 0 ||
6044 g_em->dst_offset_x != 0 ||
6045 g_em->dst_offset_y != 0)
6046 printf(" %d (%d): offsets %d,%d and %d,%d should be all 0\n",
6048 g_em->src_offset_x, g_em->src_offset_y,
6049 g_em->dst_offset_x, g_em->dst_offset_y);
6051 if (g_em->width != TILEX ||
6052 g_em->height != TILEY)
6053 printf(" %d (%d): size %d,%d should be %d,%d\n",
6055 g_em->width, g_em->height, TILEX, TILEY);
6062 for (p = 0; p < 2; p++)
6064 for (i = 0; i < SPR_MAX; i++)
6066 int element = player_mapping[p][i].element_rnd;
6067 int action = player_mapping[p][i].action;
6068 int direction = player_mapping[p][i].direction;
6070 for (j = 0; j < 8; j++)
6072 int effective_element = element;
6073 int effective_action = action;
6074 int graphic = (direction == MV_NO_MOVING ?
6075 el_act2img(effective_element, effective_action) :
6076 el_act_dir2img(effective_element, effective_action,
6078 struct GraphicInfo *g = &graphic_info[graphic];
6079 struct GraphicInfo_EM *g_em = &graphic_info_em_player[p][i][7 - j];
6085 Bitmap *debug_bitmap = g_em->bitmap;
6086 int debug_src_x = g_em->src_x;
6087 int debug_src_y = g_em->src_y;
6090 int frame = getAnimationFrame(g->anim_frames,
6093 g->anim_start_frame,
6096 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x,&src_y, FALSE);
6099 g_em->bitmap = src_bitmap;
6100 g_em->src_x = src_x;
6101 g_em->src_y = src_y;
6102 g_em->src_offset_x = 0;
6103 g_em->src_offset_y = 0;
6104 g_em->dst_offset_x = 0;
6105 g_em->dst_offset_y = 0;
6106 g_em->width = TILEX;
6107 g_em->height = TILEY;
6111 if (g_em->bitmap != debug_bitmap ||
6112 g_em->src_x != debug_src_x ||
6113 g_em->src_y != debug_src_y)
6115 static int last_i = -1;
6123 printf("::: EMC GFX ERROR for p/a %d/%d -> %d ('%s', '%s', %d)",
6124 p, i, element, element_info[element].token_name,
6125 element_action_info[effective_action].suffix, direction);
6127 if (element != effective_element)
6128 printf(" [%d ('%s')]",
6130 element_info[effective_element].token_name);
6134 if (g_em->bitmap != debug_bitmap)
6135 printf(" %d: different bitmap! (0x%08x != 0x%08x)\n",
6136 j, (int)(g_em->bitmap), (int)(debug_bitmap));
6138 if (g_em->src_x != debug_src_x ||
6139 g_em->src_y != debug_src_y)
6140 printf(" frame %d: %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
6142 g_em->src_x, g_em->src_y,
6143 g_em->src_x / 32, g_em->src_y / 32,
6144 debug_src_x, debug_src_y,
6145 debug_src_x / 32, debug_src_y / 32);