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 && !game.envelope_active)
132 width = gfx.sxsize + 2 * TILEX;
133 height = gfx.sysize + 2 * TILEY;
136 if (force_redraw || setup.direct_draw)
139 int x1 = (x - SX) / TILEX, y1 = (y - SY) / TILEY;
140 int x2 = (x - SX + width) / TILEX, y2 = (y - SY + height) / TILEY;
142 if (setup.direct_draw)
143 SetDrawtoField(DRAW_BACKBUFFER);
145 for (xx = BX1; xx <= BX2; xx++)
146 for (yy = BY1; yy <= BY2; yy++)
147 if (xx >= x1 && xx <= x2 && yy >= y1 && yy <= y2)
148 DrawScreenField(xx, yy);
151 if (setup.direct_draw)
152 SetDrawtoField(DRAW_DIRECT);
155 if (setup.soft_scrolling)
157 int fx = FX, fy = FY;
159 fx += (ScreenMovDir & (MV_LEFT|MV_RIGHT) ? ScreenGfxPos : 0);
160 fy += (ScreenMovDir & (MV_UP|MV_DOWN) ? ScreenGfxPos : 0);
162 BlitBitmap(fieldbuffer, backbuffer, fx,fy, SXSIZE,SYSIZE, SX,SY);
166 BlitBitmap(drawto, window, x, y, width, height, x, y);
172 DrawBuffer *buffer = (drawto_field == window ? backbuffer : drawto_field);
174 if (setup.direct_draw && game_status == GAME_MODE_PLAYING)
175 redraw_mask &= ~REDRAW_MAIN;
177 if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD)
178 redraw_mask |= REDRAW_FIELD;
180 if (redraw_mask & REDRAW_FIELD)
181 redraw_mask &= ~REDRAW_TILES;
183 if (redraw_mask == REDRAW_NONE)
186 if (global.fps_slowdown && game_status == GAME_MODE_PLAYING)
188 static boolean last_frame_skipped = FALSE;
189 boolean skip_even_when_not_scrolling = TRUE;
190 boolean just_scrolling = (ScreenMovDir != 0);
191 boolean verbose = FALSE;
193 if (global.fps_slowdown_factor > 1 &&
194 (FrameCounter % global.fps_slowdown_factor) &&
195 (just_scrolling || skip_even_when_not_scrolling))
197 redraw_mask &= ~REDRAW_MAIN;
199 last_frame_skipped = TRUE;
202 printf("FRAME SKIPPED\n");
206 if (last_frame_skipped)
207 redraw_mask |= REDRAW_FIELD;
209 last_frame_skipped = FALSE;
212 printf("frame not skipped\n");
216 /* synchronize X11 graphics at this point; if we would synchronize the
217 display immediately after the buffer switching (after the XFlush),
218 this could mean that we have to wait for the graphics to complete,
219 although we could go on doing calculations for the next frame */
223 if (redraw_mask & REDRAW_ALL)
225 BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
229 if (redraw_mask & REDRAW_FIELD)
231 if (game_status != GAME_MODE_PLAYING ||
232 redraw_mask & REDRAW_FROM_BACKBUFFER)
234 BlitBitmap(backbuffer, window,
235 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE, REAL_SX, REAL_SY);
239 int fx = FX, fy = FY;
241 if (setup.soft_scrolling)
243 fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
244 fy += (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
247 if (setup.soft_scrolling ||
248 ABS(ScreenMovPos) + ScrollStepSize == TILEX ||
249 ABS(ScreenMovPos) == ScrollStepSize ||
250 redraw_tiles > REDRAWTILES_THRESHOLD)
252 BlitBitmap(buffer, window, fx, fy, SXSIZE, SYSIZE, SX, SY);
256 printf("redrawing all (ScreenGfxPos == %d) because %s\n",
258 (setup.soft_scrolling ?
259 "setup.soft_scrolling" :
260 ABS(ScreenGfxPos) + ScrollStepSize == TILEX ?
261 "ABS(ScreenGfxPos) + ScrollStepSize == TILEX" :
262 ABS(ScreenGfxPos) == ScrollStepSize ?
263 "ABS(ScreenGfxPos) == ScrollStepSize" :
264 "redraw_tiles > REDRAWTILES_THRESHOLD"));
270 redraw_mask &= ~REDRAW_MAIN;
273 if (redraw_mask & REDRAW_DOORS)
275 if (redraw_mask & REDRAW_DOOR_1)
276 BlitBitmap(backbuffer, window, DX, DY, DXSIZE, DYSIZE, DX, DY);
278 if (redraw_mask & REDRAW_DOOR_2)
281 if ((redraw_mask & REDRAW_DOOR_2) == REDRAW_DOOR_2)
283 BlitBitmap(backbuffer, window, VX, VY, VXSIZE, VYSIZE, VX, VY);
287 if (redraw_mask & REDRAW_VIDEO_1)
288 BlitBitmap(backbuffer, window,
289 VX + VIDEO_DISPLAY1_XPOS, VY + VIDEO_DISPLAY1_YPOS,
290 VIDEO_DISPLAY_XSIZE, VIDEO_DISPLAY_YSIZE,
291 VX + VIDEO_DISPLAY1_XPOS, VY + VIDEO_DISPLAY1_YPOS);
292 if (redraw_mask & REDRAW_VIDEO_2)
293 BlitBitmap(backbuffer, window,
294 VX + VIDEO_DISPLAY2_XPOS, VY + VIDEO_DISPLAY2_YPOS,
295 VIDEO_DISPLAY_XSIZE, VIDEO_DISPLAY_YSIZE,
296 VX + VIDEO_DISPLAY2_XPOS, VY + VIDEO_DISPLAY2_YPOS);
297 if (redraw_mask & REDRAW_VIDEO_3)
298 BlitBitmap(backbuffer, window,
299 VX + VIDEO_CONTROL_XPOS, VY + VIDEO_CONTROL_YPOS,
300 VIDEO_CONTROL_XSIZE, VIDEO_CONTROL_YSIZE,
301 VX + VIDEO_CONTROL_XPOS, VY + VIDEO_CONTROL_YPOS);
306 if (redraw_mask & REDRAW_DOOR_3)
307 BlitBitmap(backbuffer, window, EX, EY, EXSIZE, EYSIZE, EX, EY);
309 redraw_mask &= ~REDRAW_DOORS;
312 if (redraw_mask & REDRAW_MICROLEVEL)
314 BlitBitmap(backbuffer, window, SX, SY + 10 * TILEY, SXSIZE, 7 * TILEY,
315 SX, SY + 10 * TILEY);
317 redraw_mask &= ~REDRAW_MICROLEVEL;
320 if (redraw_mask & REDRAW_TILES)
322 for (x = 0; x < SCR_FIELDX; x++)
323 for (y = 0 ; y < SCR_FIELDY; y++)
324 if (redraw[redraw_x1 + x][redraw_y1 + y])
325 BlitBitmap(buffer, window,
326 FX + x * TILEX, FY + y * TILEY, TILEX, TILEY,
327 SX + x * TILEX, SY + y * TILEY);
330 if (redraw_mask & REDRAW_FPS) /* display frames per second */
335 sprintf(info1, " (only every %d. frame)", global.fps_slowdown_factor);
336 if (!global.fps_slowdown)
339 sprintf(text, "%.1f fps%s", global.frames_per_second, info1);
340 DrawTextExt(window, SX, SY, text, FONT_TEXT_2, BLIT_OPAQUE);
345 for (x = 0; x < MAX_BUF_XSIZE; x++)
346 for (y = 0; y < MAX_BUF_YSIZE; y++)
349 redraw_mask = REDRAW_NONE;
355 long fading_delay = 300;
357 if (setup.fading && (redraw_mask & REDRAW_FIELD))
364 ClearRectangle(window, REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
367 for (i = 0; i < 2 * FULL_SYSIZE; i++)
369 for (y = 0; y < FULL_SYSIZE; y++)
371 BlitBitmap(backbuffer, window,
372 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
380 for (i = 1; i < FULL_SYSIZE; i+=2)
381 BlitBitmap(backbuffer, window,
382 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
388 SetClipOrigin(clip_gc[PIX_FADEMASK], 0, 0);
389 BlitBitmapMasked(backbuffer, window,
390 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
395 SetClipOrigin(clip_gc[PIX_FADEMASK], -1, -1);
396 BlitBitmapMasked(backbuffer, window,
397 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
402 SetClipOrigin(clip_gc[PIX_FADEMASK], 0, -1);
403 BlitBitmapMasked(backbuffer, window,
404 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
409 SetClipOrigin(clip_gc[PIX_FADEMASK], -1, 0);
410 BlitBitmapMasked(backbuffer, window,
411 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
416 redraw_mask &= ~REDRAW_MAIN;
423 void SetMainBackgroundImage(int graphic)
425 SetMainBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
426 graphic_info[graphic].bitmap ?
427 graphic_info[graphic].bitmap :
428 graphic_info[IMG_BACKGROUND].bitmap);
431 void SetDoorBackgroundImage(int graphic)
433 SetDoorBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
434 graphic_info[graphic].bitmap ?
435 graphic_info[graphic].bitmap :
436 graphic_info[IMG_BACKGROUND].bitmap);
439 void DrawBackground(int dest_x, int dest_y, int width, int height)
441 ClearRectangleOnBackground(backbuffer, dest_x, dest_y, width, height);
443 redraw_mask |= REDRAW_FIELD;
448 DrawBackground(REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
450 if (setup.soft_scrolling && game_status == GAME_MODE_PLAYING)
452 ClearRectangle(fieldbuffer, 0, 0, FXSIZE, FYSIZE);
453 SetDrawtoField(DRAW_BUFFERED);
456 SetDrawtoField(DRAW_BACKBUFFER);
458 if (setup.direct_draw && game_status == GAME_MODE_PLAYING)
460 ClearRectangle(window, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
461 SetDrawtoField(DRAW_DIRECT);
465 void MarkTileDirty(int x, int y)
467 int xx = redraw_x1 + x;
468 int yy = redraw_y1 + y;
473 redraw[xx][yy] = TRUE;
474 redraw_mask |= REDRAW_TILES;
477 void SetBorderElement()
481 BorderElement = EL_EMPTY;
483 for (y = 0; y < lev_fieldy && BorderElement == EL_EMPTY; y++)
485 for (x = 0; x < lev_fieldx; x++)
487 if (!IS_INDESTRUCTIBLE(Feld[x][y]))
488 BorderElement = EL_STEELWALL;
490 if (y != 0 && y != lev_fieldy - 1 && x != lev_fieldx - 1)
496 void SetRandomAnimationValue(int x, int y)
498 gfx.anim_random_frame = GfxRandom[x][y];
501 inline int getGraphicAnimationFrame(int graphic, int sync_frame)
503 /* animation synchronized with global frame counter, not move position */
504 if (graphic_info[graphic].anim_global_sync || sync_frame < 0)
505 sync_frame = FrameCounter;
507 return getAnimationFrame(graphic_info[graphic].anim_frames,
508 graphic_info[graphic].anim_delay,
509 graphic_info[graphic].anim_mode,
510 graphic_info[graphic].anim_start_frame,
514 inline void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
515 int graphic, int sync_frame, int mask_mode)
517 int frame = getGraphicAnimationFrame(graphic, sync_frame);
519 if (mask_mode == USE_MASKING)
520 DrawGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
522 DrawGraphicExt(dst_bitmap, x, y, graphic, frame);
525 inline void DrawGraphicAnimation(int x, int y, int graphic)
527 int lx = LEVELX(x), ly = LEVELY(y);
529 if (!IN_SCR_FIELD(x, y))
532 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
533 graphic, GfxFrame[lx][ly], NO_MASKING);
537 void DrawLevelGraphicAnimation(int x, int y, int graphic)
539 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
542 void DrawLevelElementAnimation(int x, int y, int element)
545 int graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
547 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
549 DrawGraphicAnimation(SCREENX(x), SCREENY(y), el2img(element));
553 inline void DrawLevelGraphicAnimationIfNeeded(int x, int y, int graphic)
555 int sx = SCREENX(x), sy = SCREENY(y);
557 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
560 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
563 DrawGraphicAnimation(sx, sy, graphic);
565 if (GFX_CRUMBLED(Feld[x][y]))
566 DrawLevelFieldCrumbledSand(x, y);
569 void DrawLevelElementAnimationIfNeeded(int x, int y, int element)
571 int sx = SCREENX(x), sy = SCREENY(y);
574 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
577 graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
579 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
582 DrawGraphicAnimation(sx, sy, graphic);
584 if (GFX_CRUMBLED(element))
585 DrawLevelFieldCrumbledSand(x, y);
588 static int getPlayerGraphic(struct PlayerInfo *player, int move_dir)
590 if (player->use_murphy_graphic)
592 /* this works only because currently only one player can be "murphy" ... */
593 static int last_horizontal_dir = MV_LEFT;
594 int graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, move_dir);
596 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
597 last_horizontal_dir = move_dir;
599 if (graphic == IMG_SP_MURPHY) /* undefined => use special graphic */
601 int direction = (player->is_snapping ? move_dir : last_horizontal_dir);
603 graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, direction);
609 return el_act_dir2img(player->element_nr, player->GfxAction, move_dir);
612 static boolean equalGraphics(int graphic1, int graphic2)
614 struct GraphicInfo *g1 = &graphic_info[graphic1];
615 struct GraphicInfo *g2 = &graphic_info[graphic2];
617 return (g1->bitmap == g2->bitmap &&
618 g1->src_x == g2->src_x &&
619 g1->src_y == g2->src_y &&
620 g1->anim_frames == g2->anim_frames &&
621 g1->anim_delay == g2->anim_delay &&
622 g1->anim_mode == g2->anim_mode);
625 void DrawAllPlayers()
629 for (i = 0; i < MAX_PLAYERS; i++)
630 if (stored_player[i].active)
631 DrawPlayer(&stored_player[i]);
634 void DrawPlayerField(int x, int y)
636 if (!IS_PLAYER(x, y))
639 DrawPlayer(PLAYERINFO(x, y));
642 void DrawPlayer(struct PlayerInfo *player)
646 int move_dir = player->MovDir;
648 int last_jx = player->last_jx;
649 int last_jy = player->last_jy;
650 int next_jx = jx + (jx - last_jx);
651 int next_jy = jy + (jy - last_jy);
652 boolean player_is_moving = (last_jx != jx || last_jy != jy ? TRUE : FALSE);
654 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? +1 : 0);
655 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? +1 : 0);
656 int last_jx = (player->is_moving ? jx - dx : jx);
657 int last_jy = (player->is_moving ? jy - dy : jy);
658 int next_jx = jx + dx;
659 int next_jy = jy + dy;
660 boolean player_is_moving = (player->MovPos ? TRUE : FALSE);
662 int sx = SCREENX(jx), sy = SCREENY(jy);
663 int sxx = 0, syy = 0;
664 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
666 int action = ACTION_DEFAULT;
667 int last_player_graphic = getPlayerGraphic(player, move_dir);
668 int last_player_frame = player->Frame;
671 if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
675 if (!IN_LEV_FIELD(jx, jy))
677 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
678 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
679 printf("DrawPlayerField(): This should never happen!\n");
684 if (element == EL_EXPLOSION)
687 action = (player->is_pushing ? ACTION_PUSHING :
688 player->is_digging ? ACTION_DIGGING :
689 player->is_collecting ? ACTION_COLLECTING :
690 player->is_moving ? ACTION_MOVING :
691 player->is_snapping ? ACTION_SNAPPING :
692 player->is_dropping ? ACTION_DROPPING :
693 player->is_waiting ? player->action_waiting : ACTION_DEFAULT);
695 InitPlayerGfxAnimation(player, action, move_dir);
697 /* ----------------------------------------------------------------------- */
698 /* draw things in the field the player is leaving, if needed */
699 /* ----------------------------------------------------------------------- */
702 if (player->is_moving)
704 if (player_is_moving)
707 if (Back[last_jx][last_jy] && IS_DRAWABLE(last_element))
709 DrawLevelElement(last_jx, last_jy, Back[last_jx][last_jy]);
711 if (last_element == EL_DYNAMITE_ACTIVE ||
712 last_element == EL_SP_DISK_RED_ACTIVE)
713 DrawDynamite(last_jx, last_jy);
715 DrawLevelFieldThruMask(last_jx, last_jy);
717 else if (last_element == EL_DYNAMITE_ACTIVE ||
718 last_element == EL_SP_DISK_RED_ACTIVE)
719 DrawDynamite(last_jx, last_jy);
721 DrawLevelField(last_jx, last_jy);
723 if (player->is_pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
724 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
727 if (!IN_SCR_FIELD(sx, sy))
730 if (setup.direct_draw)
731 SetDrawtoField(DRAW_BUFFERED);
733 /* ----------------------------------------------------------------------- */
734 /* draw things behind the player, if needed */
735 /* ----------------------------------------------------------------------- */
738 DrawLevelElement(jx, jy, Back[jx][jy]);
739 else if (IS_ACTIVE_BOMB(element))
740 DrawLevelElement(jx, jy, EL_EMPTY);
743 if (player_is_moving && GfxElement[jx][jy] != EL_UNDEFINED)
745 if (GFX_CRUMBLED(GfxElement[jx][jy]))
746 DrawLevelFieldCrumbledSandDigging(jx, jy, move_dir, player->StepFrame);
749 int old_element = GfxElement[jx][jy];
750 int old_graphic = el_act_dir2img(old_element, action, move_dir);
751 int frame = getGraphicAnimationFrame(old_graphic, player->StepFrame);
753 DrawGraphic(sx, sy, old_graphic, frame);
758 GfxElement[jx][jy] = EL_UNDEFINED;
760 DrawLevelField(jx, jy);
764 /* ----------------------------------------------------------------------- */
765 /* draw player himself */
766 /* ----------------------------------------------------------------------- */
770 graphic = getPlayerGraphic(player, move_dir);
772 /* in the case of changed player action or direction, prevent the current
773 animation frame from being restarted for identical animations */
774 if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic))
775 player->Frame = last_player_frame;
779 if (player->use_murphy_graphic)
781 static int last_horizontal_dir = MV_LEFT;
783 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
784 last_horizontal_dir = move_dir;
786 graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, move_dir);
788 if (graphic == IMG_SP_MURPHY) /* undefined => use special graphic */
790 int direction = (player->is_snapping ? move_dir : last_horizontal_dir);
792 graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, direction);
796 graphic = el_act_dir2img(player->element_nr, player->GfxAction, move_dir);
800 frame = getGraphicAnimationFrame(graphic, player->Frame);
804 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
805 sxx = player->GfxPos;
807 syy = player->GfxPos;
810 if (!setup.soft_scrolling && ScreenMovPos)
813 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
815 if (SHIELD_ON(player))
817 int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
818 IMG_SHIELD_NORMAL_ACTIVE);
819 int frame = getGraphicAnimationFrame(graphic, -1);
821 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
824 /* ----------------------------------------------------------------------- */
825 /* draw things the player is pushing, if needed */
826 /* ----------------------------------------------------------------------- */
829 printf("::: %d, %d [%d, %d] [%d]\n",
830 player->is_pushing, player_is_moving, player->GfxAction,
831 player->is_moving, player_is_moving);
835 if (player->is_pushing && player->is_moving)
837 if (player->is_pushing && player_is_moving)
840 int px = SCREENX(next_jx), py = SCREENY(next_jy);
842 if (Back[next_jx][next_jy])
843 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
845 if ((sxx || syy) && element == EL_SOKOBAN_OBJECT)
846 DrawGraphicShiftedThruMask(px, py, sxx, syy, IMG_SOKOBAN_OBJECT, 0,
850 int element = MovingOrBlocked2Element(next_jx, next_jy);
851 int graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
853 int frame = getGraphicAnimationFrame(graphic, player->StepFrame);
855 int frame = getGraphicAnimationFrame(graphic, player->Frame);
858 DrawGraphicShifted(px, py, sxx, syy, graphic, frame,
859 NO_CUTTING, NO_MASKING);
863 /* ----------------------------------------------------------------------- */
864 /* draw things in front of player (active dynamite or dynabombs) */
865 /* ----------------------------------------------------------------------- */
867 if (IS_ACTIVE_BOMB(element))
869 graphic = el2img(element);
870 frame = getGraphicAnimationFrame(graphic, GfxFrame[jx][jy]);
872 if (game.emulation == EMU_SUPAPLEX)
873 DrawGraphic(sx, sy, IMG_SP_DISK_RED, frame);
875 DrawGraphicThruMask(sx, sy, graphic, frame);
878 if (player_is_moving && last_element == EL_EXPLOSION)
880 int graphic = el_act2img(GfxElement[last_jx][last_jy], ACTION_EXPLODING);
881 int delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2);
882 int phase = ExplodePhase[last_jx][last_jy] - 1;
883 int frame = getGraphicAnimationFrame(graphic, phase - delay);
886 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy), graphic, frame);
889 /* ----------------------------------------------------------------------- */
890 /* draw elements the player is just walking/passing through/under */
891 /* ----------------------------------------------------------------------- */
893 if (player_is_moving)
895 /* handle the field the player is leaving ... */
896 if (IS_ACCESSIBLE_INSIDE(last_element))
897 DrawLevelField(last_jx, last_jy);
898 else if (IS_ACCESSIBLE_UNDER(last_element))
899 DrawLevelFieldThruMask(last_jx, last_jy);
903 /* do not redraw accessible elements if the player is just pushing them */
904 if (!player_is_moving || !player->is_pushing)
906 /* ... and the field the player is entering */
907 if (IS_ACCESSIBLE_INSIDE(element))
908 DrawLevelField(jx, jy);
909 else if (IS_ACCESSIBLE_UNDER(element))
910 DrawLevelFieldThruMask(jx, jy);
916 /* !!! I have forgotton what this should be good for !!! */
917 /* !!! causes player being visible when pushing from within tubes !!! */
918 if (!player->is_pushing)
921 /* ... and the field the player is entering */
922 if (IS_ACCESSIBLE_INSIDE(element))
923 DrawLevelField(jx, jy);
924 else if (IS_ACCESSIBLE_UNDER(element))
925 DrawLevelFieldThruMask(jx, jy);
929 if (setup.direct_draw)
931 int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
932 int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
933 int x_size = TILEX * (1 + ABS(jx - last_jx));
934 int y_size = TILEY * (1 + ABS(jy - last_jy));
936 BlitBitmap(drawto_field, window,
937 dest_x, dest_y, x_size, y_size, dest_x, dest_y);
938 SetDrawtoField(DRAW_DIRECT);
941 MarkTileDirty(sx, sy);
944 inline void getGraphicSourceExt(int graphic, int frame, Bitmap **bitmap,
945 int *x, int *y, boolean get_backside)
947 struct GraphicInfo *g = &graphic_info[graphic];
948 int src_x = g->src_x + (get_backside ? g->offset2_x : 0);
949 int src_y = g->src_y + (get_backside ? g->offset2_y : 0);
953 if (g->offset_y == 0) /* frames are ordered horizontally */
955 int max_width = g->anim_frames_per_line * g->width;
957 int pos = (src_y / g->height) * max_width + src_x + frame * g->offset_x;
959 *x = pos % max_width;
960 *y = src_y % g->height + pos / max_width * g->height;
962 *x = (src_x + frame * g->offset_x) % max_width;
963 *y = src_y + (src_x + frame * g->offset_x) / max_width * g->height;
966 else if (g->offset_x == 0) /* frames are ordered vertically */
968 int max_height = g->anim_frames_per_line * g->height;
970 int pos = (src_x / g->width) * max_height + src_y + frame * g->offset_y;
972 *x = src_x % g->width + pos / max_height * g->width;
973 *y = pos % max_height;
975 *x = src_x + (src_y + frame * g->offset_y) / max_height * g->width;
976 *y = (src_y + frame * g->offset_y) % max_height;
979 else /* frames are ordered diagonally */
981 *x = src_x + frame * g->offset_x;
982 *y = src_y + frame * g->offset_y;
986 void getGraphicSource(int graphic, int frame, Bitmap **bitmap, int *x, int *y)
988 getGraphicSourceExt(graphic, frame, bitmap, x, y, FALSE);
991 void DrawGraphic(int x, int y, int graphic, int frame)
994 if (!IN_SCR_FIELD(x, y))
996 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
997 printf("DrawGraphic(): This should never happen!\n");
1002 DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic, frame);
1003 MarkTileDirty(x, y);
1006 void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
1012 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1013 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
1016 void DrawGraphicThruMask(int x, int y, int graphic, int frame)
1019 if (!IN_SCR_FIELD(x, y))
1021 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
1022 printf("DrawGraphicThruMask(): This should never happen!\n");
1027 DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY, graphic,
1029 MarkTileDirty(x, y);
1032 void DrawGraphicThruMaskExt(DrawBuffer *d, int dest_x, int dest_y, int graphic,
1040 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1041 drawing_gc = src_bitmap->stored_clip_gc;
1043 GC drawing_gc = src_bitmap->stored_clip_gc;
1044 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
1045 int src_x = graphic_info[graphic].src_x;
1046 int src_y = graphic_info[graphic].src_y;
1047 int offset_x = graphic_info[graphic].offset_x;
1048 int offset_y = graphic_info[graphic].offset_y;
1050 src_x += frame * offset_x;
1051 src_y += frame * offset_y;
1055 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1056 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dest_x, dest_y);
1059 void DrawMiniGraphic(int x, int y, int graphic)
1061 DrawMiniGraphicExt(drawto, SX + x * MINI_TILEX,SY + y * MINI_TILEY, graphic);
1062 MarkTileDirty(x / 2, y / 2);
1065 void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1067 struct GraphicInfo *g = &graphic_info[graphic];
1068 int mini_startx = 0;
1069 int mini_starty = g->bitmap->height * 2 / 3;
1071 *bitmap = g->bitmap;
1072 *x = mini_startx + g->src_x / 2;
1073 *y = mini_starty + g->src_y / 2;
1076 void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
1081 getMiniGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1082 BlitBitmap(src_bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
1085 void DrawGraphicShifted(int x, int y, int dx, int dy, int graphic, int frame,
1086 int cut_mode, int mask_mode)
1091 int width = TILEX, height = TILEY;
1097 DrawGraphic(x, y, graphic, frame);
1101 if (dx || dy) /* shifted graphic */
1103 if (x < BX1) /* object enters playfield from the left */
1110 else if (x > BX2) /* object enters playfield from the right */
1116 else if (x==BX1 && dx < 0) /* object leaves playfield to the left */
1122 else if (x==BX2 && dx > 0) /* object leaves playfield to the right */
1124 else if (dx) /* general horizontal movement */
1125 MarkTileDirty(x + SIGN(dx), y);
1127 if (y < BY1) /* object enters playfield from the top */
1129 if (cut_mode==CUT_BELOW) /* object completely above top border */
1137 else if (y > BY2) /* object enters playfield from the bottom */
1143 else if (y==BY1 && dy < 0) /* object leaves playfield to the top */
1149 else if (dy > 0 && cut_mode == CUT_ABOVE)
1151 if (y == BY2) /* object completely above bottom border */
1157 MarkTileDirty(x, y + 1);
1158 } /* object leaves playfield to the bottom */
1159 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1161 else if (dy) /* general vertical movement */
1162 MarkTileDirty(x, y + SIGN(dy));
1166 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1168 src_bitmap = graphic_info[graphic].bitmap;
1169 src_x = graphic_info[graphic].src_x;
1170 src_y = graphic_info[graphic].src_y;
1171 offset_x = graphic_info[graphic].offset_x;
1172 offset_y = graphic_info[graphic].offset_y;
1174 src_x += frame * offset_x;
1175 src_y += frame * offset_y;
1178 drawing_gc = src_bitmap->stored_clip_gc;
1183 dest_x = FX + x * TILEX + dx;
1184 dest_y = FY + y * TILEY + dy;
1187 if (!IN_SCR_FIELD(x,y))
1189 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1190 printf("DrawGraphicShifted(): This should never happen!\n");
1195 if (mask_mode == USE_MASKING)
1197 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1198 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
1202 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1205 MarkTileDirty(x, y);
1208 void DrawGraphicShiftedThruMask(int x, int y, int dx, int dy, int graphic,
1209 int frame, int cut_mode)
1211 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, USE_MASKING);
1214 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1215 int cut_mode, int mask_mode)
1217 int lx = LEVELX(x), ly = LEVELY(y);
1221 if (IN_LEV_FIELD(lx, ly))
1223 SetRandomAnimationValue(lx, ly);
1225 graphic = el_act_dir2img(element, GfxAction[lx][ly], GfxDir[lx][ly]);
1226 frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
1228 else /* border element */
1230 graphic = el2img(element);
1231 frame = getGraphicAnimationFrame(graphic, -1);
1234 if (element == EL_EXPANDABLE_WALL)
1236 boolean left_stopped = FALSE, right_stopped = FALSE;
1238 if (!IN_LEV_FIELD(lx - 1, ly) || IS_WALL(Feld[lx - 1][ly]))
1239 left_stopped = TRUE;
1240 if (!IN_LEV_FIELD(lx + 1, ly) || IS_WALL(Feld[lx + 1][ly]))
1241 right_stopped = TRUE;
1243 if (left_stopped && right_stopped)
1245 else if (left_stopped)
1247 graphic = IMG_EXPANDABLE_WALL_GROWING_RIGHT;
1248 frame = graphic_info[graphic].anim_frames - 1;
1250 else if (right_stopped)
1252 graphic = IMG_EXPANDABLE_WALL_GROWING_LEFT;
1253 frame = graphic_info[graphic].anim_frames - 1;
1258 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
1259 else if (mask_mode == USE_MASKING)
1260 DrawGraphicThruMask(x, y, graphic, frame);
1262 DrawGraphic(x, y, graphic, frame);
1265 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1266 int cut_mode, int mask_mode)
1268 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1269 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1270 cut_mode, mask_mode);
1273 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1276 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1279 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1282 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1285 void DrawLevelElementThruMask(int x, int y, int element)
1287 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1290 void DrawLevelFieldThruMask(int x, int y)
1292 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1295 #define TILE_GFX_ELEMENT(x, y) \
1296 (GfxElement[x][y] != EL_UNDEFINED && Feld[x][y] != EL_EXPLOSION ? \
1297 GfxElement[x][y] : Feld[x][y])
1299 static void DrawLevelFieldCrumbledSandExt(int x, int y, int graphic, int frame)
1303 int sx = SCREENX(x), sy = SCREENY(y);
1305 int width, height, cx, cy, i;
1307 int crumbled_border_size = graphic_info[graphic].border_size;
1309 int snip = TILEX / 8; /* number of border pixels from "crumbled graphic" */
1311 static int xy[4][2] =
1320 if (x == 0 && y == 7)
1321 printf("::: %d, %d [%d]\n", GfxElement[x][y], Feld[x][y],
1322 crumbled_border_size);
1325 if (!IN_LEV_FIELD(x, y))
1328 element = TILE_GFX_ELEMENT(x, y);
1330 /* crumble field itself */
1331 if (GFX_CRUMBLED(element) && !IS_MOVING(x, y))
1333 if (!IN_SCR_FIELD(sx, sy))
1336 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1338 for (i = 0; i < 4; i++)
1340 int xx = x + xy[i][0];
1341 int yy = y + xy[i][1];
1344 element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
1347 element = (IN_LEV_FIELD(xx, yy) ? Feld[xx][yy] : BorderElement);
1350 /* check if neighbour field is of same type */
1351 if (GFX_CRUMBLED(element) && !IS_MOVING(xx, yy))
1355 if (Feld[x][y] == EL_CUSTOM_START + 123)
1356 printf("::: crumble [%d] THE CHAOS ENGINE (%d, %d): %d, %d\n",
1357 i, Feld[x][y], element,
1358 GFX_CRUMBLED(element), IS_MOVING(x, y));
1361 if (i == 1 || i == 2)
1363 width = crumbled_border_size;
1365 cx = (i == 2 ? TILEX - crumbled_border_size : 0);
1371 height = crumbled_border_size;
1373 cy = (i == 3 ? TILEY - crumbled_border_size : 0);
1376 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1377 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
1380 MarkTileDirty(sx, sy);
1382 else /* crumble neighbour fields */
1385 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1388 for (i = 0; i < 4; i++)
1390 int xx = x + xy[i][0];
1391 int yy = y + xy[i][1];
1392 int sxx = sx + xy[i][0];
1393 int syy = sy + xy[i][1];
1396 if (!IN_LEV_FIELD(xx, yy) ||
1397 !IN_SCR_FIELD(sxx, syy) ||
1401 element = TILE_GFX_ELEMENT(xx, yy);
1403 if (!GFX_CRUMBLED(element))
1406 if (!IN_LEV_FIELD(xx, yy) ||
1407 !IN_SCR_FIELD(sxx, syy) ||
1408 !GFX_CRUMBLED(Feld[xx][yy]) ||
1414 graphic = el_act2crm(Feld[xx][yy], ACTION_DEFAULT);
1415 crumbled_border_size = graphic_info[graphic].border_size;
1417 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1420 if (i == 1 || i == 2)
1422 width = crumbled_border_size;
1424 cx = (i == 1 ? TILEX - crumbled_border_size : 0);
1430 height = crumbled_border_size;
1432 cy = (i == 0 ? TILEY - crumbled_border_size : 0);
1435 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1436 width, height, FX + sxx * TILEX + cx, FY + syy * TILEY + cy);
1438 MarkTileDirty(sxx, syy);
1443 void DrawLevelFieldCrumbledSand(int x, int y)
1448 if (!IN_LEV_FIELD(x, y))
1451 graphic = el_act2crm(Feld[x][y], ACTION_DEFAULT);
1453 DrawLevelFieldCrumbledSandExt(x, y, graphic, 0);
1455 DrawLevelFieldCrumbledSandExt(x, y, IMG_SAND_CRUMBLED, 0);
1459 void DrawLevelFieldCrumbledSandDigging(int x, int y, int direction,
1463 int graphic1 = el_act_dir2img(GfxElement[x][y], ACTION_DIGGING, direction);
1464 int graphic2 = el_act_dir2crm(GfxElement[x][y], ACTION_DIGGING, direction);
1466 int graphic1 = el_act_dir2img(EL_SAND, ACTION_DIGGING, direction);
1467 int graphic2 = el_act_dir2img(EL_SAND_CRUMBLED, ACTION_DIGGING, direction);
1469 int frame1 = getGraphicAnimationFrame(graphic1, step_frame);
1470 int frame2 = getGraphicAnimationFrame(graphic2, step_frame);
1471 int sx = SCREENX(x), sy = SCREENY(y);
1473 DrawGraphic(sx, sy, graphic1, frame1);
1474 DrawLevelFieldCrumbledSandExt(x, y, graphic2, frame2);
1477 void DrawLevelFieldCrumbledSandNeighbours(int x, int y)
1479 int sx = SCREENX(x), sy = SCREENY(y);
1480 static int xy[4][2] =
1489 for (i = 0; i < 4; i++)
1491 int xx = x + xy[i][0];
1492 int yy = y + xy[i][1];
1493 int sxx = sx + xy[i][0];
1494 int syy = sy + xy[i][1];
1496 if (!IN_LEV_FIELD(xx, yy) ||
1497 !IN_SCR_FIELD(sxx, syy) ||
1498 !GFX_CRUMBLED(Feld[xx][yy]) ||
1502 DrawLevelField(xx, yy);
1506 static int getBorderElement(int x, int y)
1510 { EL_STEELWALL_TOPLEFT, EL_INVISIBLE_STEELWALL_TOPLEFT },
1511 { EL_STEELWALL_TOPRIGHT, EL_INVISIBLE_STEELWALL_TOPRIGHT },
1512 { EL_STEELWALL_BOTTOMLEFT, EL_INVISIBLE_STEELWALL_BOTTOMLEFT },
1513 { EL_STEELWALL_BOTTOMRIGHT, EL_INVISIBLE_STEELWALL_BOTTOMRIGHT },
1514 { EL_STEELWALL_VERTICAL, EL_INVISIBLE_STEELWALL_VERTICAL },
1515 { EL_STEELWALL_HORIZONTAL, EL_INVISIBLE_STEELWALL_HORIZONTAL },
1516 { EL_STEELWALL, EL_INVISIBLE_STEELWALL }
1518 int steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
1519 int steel_position = (x == -1 && y == -1 ? 0 :
1520 x == lev_fieldx && y == -1 ? 1 :
1521 x == -1 && y == lev_fieldy ? 2 :
1522 x == lev_fieldx && y == lev_fieldy ? 3 :
1523 x == -1 || x == lev_fieldx ? 4 :
1524 y == -1 || y == lev_fieldy ? 5 : 6);
1526 return border[steel_position][steel_type];
1529 void DrawScreenElement(int x, int y, int element)
1531 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1532 DrawLevelFieldCrumbledSand(LEVELX(x), LEVELY(y));
1535 void DrawLevelElement(int x, int y, int element)
1537 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1538 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1541 void DrawScreenField(int x, int y)
1543 int lx = LEVELX(x), ly = LEVELY(y);
1544 int element, content;
1546 if (!IN_LEV_FIELD(lx, ly))
1548 if (lx < -1 || lx > lev_fieldx || ly < -1 || ly > lev_fieldy)
1551 element = getBorderElement(lx, ly);
1553 DrawScreenElement(x, y, element);
1557 element = Feld[lx][ly];
1558 content = Store[lx][ly];
1560 if (IS_MOVING(lx, ly))
1562 int horiz_move = (MovDir[lx][ly] == MV_LEFT || MovDir[lx][ly] == MV_RIGHT);
1563 boolean cut_mode = NO_CUTTING;
1565 if (element == EL_QUICKSAND_EMPTYING ||
1566 element == EL_MAGIC_WALL_EMPTYING ||
1567 element == EL_BD_MAGIC_WALL_EMPTYING ||
1568 element == EL_AMOEBA_DROPPING)
1569 cut_mode = CUT_ABOVE;
1570 else if (element == EL_QUICKSAND_FILLING ||
1571 element == EL_MAGIC_WALL_FILLING ||
1572 element == EL_BD_MAGIC_WALL_FILLING)
1573 cut_mode = CUT_BELOW;
1575 if (cut_mode == CUT_ABOVE)
1576 DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1578 DrawScreenElement(x, y, EL_EMPTY);
1581 DrawScreenElementShifted(x, y, MovPos[lx][ly], 0, element, NO_CUTTING);
1582 else if (cut_mode == NO_CUTTING)
1583 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], element, cut_mode);
1585 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], content, cut_mode);
1587 if (content == EL_ACID)
1589 int dir = MovDir[lx][ly];
1590 int newlx = lx + (dir == MV_LEFT ? -1 : dir == MV_RIGHT ? +1 : 0);
1591 int newly = ly + (dir == MV_UP ? -1 : dir == MV_DOWN ? +1 : 0);
1593 DrawLevelElementThruMask(newlx, newly, EL_ACID);
1596 else if (IS_BLOCKED(lx, ly))
1601 boolean cut_mode = NO_CUTTING;
1602 int element_old, content_old;
1604 Blocked2Moving(lx, ly, &oldx, &oldy);
1607 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1608 MovDir[oldx][oldy] == MV_RIGHT);
1610 element_old = Feld[oldx][oldy];
1611 content_old = Store[oldx][oldy];
1613 if (element_old == EL_QUICKSAND_EMPTYING ||
1614 element_old == EL_MAGIC_WALL_EMPTYING ||
1615 element_old == EL_BD_MAGIC_WALL_EMPTYING ||
1616 element_old == EL_AMOEBA_DROPPING)
1617 cut_mode = CUT_ABOVE;
1619 DrawScreenElement(x, y, EL_EMPTY);
1622 DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
1624 else if (cut_mode == NO_CUTTING)
1625 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
1628 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
1631 else if (IS_DRAWABLE(element))
1632 DrawScreenElement(x, y, element);
1634 DrawScreenElement(x, y, EL_EMPTY);
1637 void DrawLevelField(int x, int y)
1639 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1640 DrawScreenField(SCREENX(x), SCREENY(y));
1641 else if (IS_MOVING(x, y))
1645 Moving2Blocked(x, y, &newx, &newy);
1646 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1647 DrawScreenField(SCREENX(newx), SCREENY(newy));
1649 else if (IS_BLOCKED(x, y))
1653 Blocked2Moving(x, y, &oldx, &oldy);
1654 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1655 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1659 void DrawMiniElement(int x, int y, int element)
1663 graphic = el2edimg(element);
1664 DrawMiniGraphic(x, y, graphic);
1667 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1669 int x = sx + scroll_x, y = sy + scroll_y;
1671 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1672 DrawMiniElement(sx, sy, EL_EMPTY);
1673 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1674 DrawMiniElement(sx, sy, Feld[x][y]);
1676 DrawMiniGraphic(sx, sy, el2edimg(getBorderElement(x, y)));
1679 void DrawEnvelopeBackground(int envelope_nr, int startx, int starty,
1680 int x, int y, int xsize, int ysize, int font_nr)
1682 int font_width = getFontWidth(font_nr);
1683 int font_height = getFontHeight(font_nr);
1684 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1687 int dst_x = SX + startx + x * font_width;
1688 int dst_y = SY + starty + y * font_height;
1689 int width = graphic_info[graphic].width;
1690 int height = graphic_info[graphic].height;
1691 int inner_width = MAX(width - 2 * font_width, font_width);
1692 int inner_height = MAX(height - 2 * font_height, font_height);
1693 int inner_sx = (width >= 3 * font_width ? font_width : 0);
1694 int inner_sy = (height >= 3 * font_height ? font_height : 0);
1695 boolean draw_masked = graphic_info[graphic].draw_masked;
1697 getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
1699 if (src_bitmap == NULL || width < font_width || height < font_height)
1701 ClearRectangle(drawto, dst_x, dst_y, font_width, font_height);
1705 src_x += (x == 0 ? 0 : x == xsize - 1 ? width - font_width :
1706 inner_sx + (x - 1) * font_width % inner_width);
1707 src_y += (y == 0 ? 0 : y == ysize - 1 ? height - font_height :
1708 inner_sy + (y - 1) * font_height % inner_height);
1712 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1713 dst_x - src_x, dst_y - src_y);
1714 BlitBitmapMasked(src_bitmap, drawto, src_x, src_y, font_width, font_height,
1718 BlitBitmap(src_bitmap, drawto, src_x, src_y, font_width, font_height,
1722 void AnimateEnvelope(int envelope_nr, int anim_mode, int action)
1724 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1726 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
1727 int mask_mode = (src_bitmap != NULL ? BLIT_MASKED : BLIT_ON_BACKGROUND);
1729 boolean draw_masked = graphic_info[graphic].draw_masked;
1730 int mask_mode = (draw_masked ? BLIT_MASKED : BLIT_ON_BACKGROUND);
1732 boolean ffwd_delay = (tape.playing && tape.fast_forward);
1733 boolean no_delay = (tape.warp_forward);
1734 unsigned long anim_delay = 0;
1735 int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
1736 int anim_delay_value = (no_delay ? 0 : frame_delay_value);
1737 int font_nr = FONT_ENVELOPE_1 + envelope_nr;
1738 int font_width = getFontWidth(font_nr);
1739 int font_height = getFontHeight(font_nr);
1740 int max_xsize = level.envelope_xsize[envelope_nr];
1741 int max_ysize = level.envelope_ysize[envelope_nr];
1742 int xstart = (anim_mode & ANIM_VERTICAL ? max_xsize : 0);
1743 int ystart = (anim_mode & ANIM_HORIZONTAL ? max_ysize : 0);
1744 int xend = max_xsize;
1745 int yend = (anim_mode != ANIM_DEFAULT ? max_ysize : 0);
1746 int xstep = (xstart < xend ? 1 : 0);
1747 int ystep = (ystart < yend || xstep == 0 ? 1 : 0);
1750 for (x = xstart, y = ystart; x <= xend && y <= yend; x += xstep, y += ystep)
1752 int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2;
1753 int ysize = (action == ACTION_CLOSING ? yend - (y - ystart) : y) + 2;
1754 int sx = (SXSIZE - xsize * font_width) / 2;
1755 int sy = (SYSIZE - ysize * font_height) / 2;
1758 SetDrawtoField(DRAW_BUFFERED);
1760 BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
1762 SetDrawtoField(DRAW_BACKBUFFER);
1764 for (yy = 0; yy < ysize; yy++) for (xx = 0; xx < xsize; xx++)
1765 DrawEnvelopeBackground(envelope_nr, sx,sy, xx,yy, xsize, ysize, font_nr);
1767 DrawTextToTextArea(SX + sx + font_width, SY + sy + font_height,
1768 level.envelope_text[envelope_nr], font_nr, max_xsize,
1769 xsize - 2, ysize - 2, mask_mode);
1771 redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
1774 WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
1778 void ShowEnvelope(int envelope_nr)
1780 int element = EL_ENVELOPE_1 + envelope_nr;
1781 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1782 int sound_opening = element_info[element].sound[ACTION_OPENING];
1783 int sound_closing = element_info[element].sound[ACTION_CLOSING];
1784 boolean ffwd_delay = (tape.playing && tape.fast_forward);
1785 boolean no_delay = (tape.warp_forward);
1786 int normal_delay_value = ONE_SECOND_DELAY / (ffwd_delay ? 2 : 1);
1787 int wait_delay_value = (no_delay ? 0 : normal_delay_value);
1788 int anim_mode = graphic_info[graphic].anim_mode;
1789 int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL:
1790 anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode);
1792 game.envelope_active = TRUE; /* needed for RedrawPlayfield() events */
1794 PlaySoundStereo(sound_opening, SOUND_MIDDLE);
1796 if (anim_mode == ANIM_DEFAULT)
1797 AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_OPENING);
1799 AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_OPENING);
1802 Delay(wait_delay_value);
1804 WaitForEventToContinue();
1806 PlaySoundStereo(sound_closing, SOUND_MIDDLE);
1808 if (anim_mode != ANIM_NONE)
1809 AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_CLOSING);
1811 if (anim_mode == ANIM_DEFAULT)
1812 AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_CLOSING);
1814 game.envelope_active = FALSE;
1816 SetDrawtoField(DRAW_BUFFERED);
1818 redraw_mask |= REDRAW_FIELD;
1822 void getMicroGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1824 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
1825 int mini_startx = src_bitmap->width * 3 / 4;
1826 int mini_starty = src_bitmap->height * 2 / 3;
1827 int src_x = mini_startx + graphic_info[graphic].src_x / 8;
1828 int src_y = mini_starty + graphic_info[graphic].src_y / 8;
1830 *bitmap = src_bitmap;
1835 void DrawMicroElement(int xpos, int ypos, int element)
1839 int graphic = el2preimg(element);
1841 getMicroGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1842 BlitBitmap(src_bitmap, drawto, src_x, src_y, MICRO_TILEX, MICRO_TILEY,
1850 SetDrawBackgroundMask(REDRAW_NONE);
1853 for (x = BX1; x <= BX2; x++)
1854 for (y = BY1; y <= BY2; y++)
1855 DrawScreenField(x, y);
1857 redraw_mask |= REDRAW_FIELD;
1860 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1864 for (x = 0; x < size_x; x++)
1865 for (y = 0; y < size_y; y++)
1866 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1868 redraw_mask |= REDRAW_FIELD;
1871 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1875 DrawBackground(xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
1877 if (lev_fieldx < STD_LEV_FIELDX)
1878 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1879 if (lev_fieldy < STD_LEV_FIELDY)
1880 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1882 xpos += MICRO_TILEX;
1883 ypos += MICRO_TILEY;
1885 for (x = -1; x <= STD_LEV_FIELDX; x++)
1887 for (y = -1; y <= STD_LEV_FIELDY; y++)
1889 int lx = from_x + x, ly = from_y + y;
1891 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1892 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1893 level.field[lx][ly]);
1894 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1
1895 && BorderElement != EL_EMPTY)
1896 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1897 getBorderElement(lx, ly));
1901 redraw_mask |= REDRAW_MICROLEVEL;
1904 #define MICROLABEL_EMPTY 0
1905 #define MICROLABEL_LEVEL_NAME 1
1906 #define MICROLABEL_CREATED_BY 2
1907 #define MICROLABEL_LEVEL_AUTHOR 3
1908 #define MICROLABEL_IMPORTED_FROM 4
1909 #define MICROLABEL_LEVEL_IMPORT_INFO 5
1911 static void DrawMicroLevelLabelExt(int mode)
1913 char label_text[MAX_OUTPUT_LINESIZE + 1];
1914 int max_len_label_text;
1915 int font_nr = FONT_TEXT_2;
1917 if (mode == MICROLABEL_CREATED_BY || mode == MICROLABEL_IMPORTED_FROM)
1918 font_nr = FONT_TEXT_3;
1920 max_len_label_text = SXSIZE / getFontWidth(font_nr);
1922 DrawBackground(SX, MICROLABEL_YPOS, SXSIZE, getFontHeight(font_nr));
1924 strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
1925 mode == MICROLABEL_CREATED_BY ? "created by" :
1926 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
1927 mode == MICROLABEL_IMPORTED_FROM ? "imported from" :
1928 mode == MICROLABEL_LEVEL_IMPORT_INFO ?
1929 leveldir_current->imported_from : ""),
1930 max_len_label_text);
1931 label_text[max_len_label_text] = '\0';
1933 if (strlen(label_text) > 0)
1935 int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
1936 int lypos = MICROLABEL_YPOS;
1938 DrawText(lxpos, lypos, label_text, font_nr);
1941 redraw_mask |= REDRAW_MICROLEVEL;
1944 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1946 static unsigned long scroll_delay = 0;
1947 static unsigned long label_delay = 0;
1948 static int from_x, from_y, scroll_direction;
1949 static int label_state, label_counter;
1950 int last_game_status = game_status; /* save current game status */
1952 /* force PREVIEW font on preview level */
1953 game_status = GAME_MODE_PSEUDO_PREVIEW;
1957 from_x = from_y = 0;
1958 scroll_direction = MV_RIGHT;
1962 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1963 DrawMicroLevelLabelExt(label_state);
1965 /* initialize delay counters */
1966 DelayReached(&scroll_delay, 0);
1967 DelayReached(&label_delay, 0);
1969 if (leveldir_current->name)
1971 int text_width = getTextWidth(leveldir_current->name, FONT_TEXT_1);
1972 int lxpos = SX + (SXSIZE - text_width) / 2;
1973 int lypos = SY + 352;
1975 DrawText(lxpos, lypos, leveldir_current->name, FONT_TEXT_1);
1978 game_status = last_game_status; /* restore current game status */
1983 /* scroll micro level, if needed */
1984 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1985 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1987 switch (scroll_direction)
1993 scroll_direction = MV_UP;
1997 if (from_x < lev_fieldx - STD_LEV_FIELDX)
2000 scroll_direction = MV_DOWN;
2007 scroll_direction = MV_RIGHT;
2011 if (from_y < lev_fieldy - STD_LEV_FIELDY)
2014 scroll_direction = MV_LEFT;
2021 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
2024 /* redraw micro level label, if needed */
2025 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
2026 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
2027 strcmp(level.author, leveldir_current->name) != 0 &&
2028 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
2030 int max_label_counter = 23;
2032 if (leveldir_current->imported_from != NULL)
2033 max_label_counter += 14;
2035 label_counter = (label_counter + 1) % max_label_counter;
2036 label_state = (label_counter >= 0 && label_counter <= 7 ?
2037 MICROLABEL_LEVEL_NAME :
2038 label_counter >= 9 && label_counter <= 12 ?
2039 MICROLABEL_CREATED_BY :
2040 label_counter >= 14 && label_counter <= 21 ?
2041 MICROLABEL_LEVEL_AUTHOR :
2042 label_counter >= 23 && label_counter <= 26 ?
2043 MICROLABEL_IMPORTED_FROM :
2044 label_counter >= 28 && label_counter <= 35 ?
2045 MICROLABEL_LEVEL_IMPORT_INFO : MICROLABEL_EMPTY);
2046 DrawMicroLevelLabelExt(label_state);
2049 game_status = last_game_status; /* restore current game status */
2052 void WaitForEventToContinue()
2054 boolean still_wait = TRUE;
2056 /* simulate releasing mouse button over last gadget, if still pressed */
2058 HandleGadgets(-1, -1, 0);
2060 button_status = MB_RELEASED;
2072 case EVENT_BUTTONPRESS:
2073 case EVENT_KEYPRESS:
2077 case EVENT_KEYRELEASE:
2078 ClearPlayerAction();
2082 HandleOtherEvents(&event);
2086 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2093 /* don't eat all CPU time */
2098 #define MAX_REQUEST_LINES 13
2099 #define MAX_REQUEST_LINE_FONT1_LEN 7
2100 #define MAX_REQUEST_LINE_FONT2_LEN 10
2102 boolean Request(char *text, unsigned int req_state)
2104 int mx, my, ty, result = -1;
2105 unsigned int old_door_state;
2106 int last_game_status = game_status; /* save current game status */
2107 int max_request_line_len = MAX_REQUEST_LINE_FONT1_LEN;
2108 int font_nr = FONT_TEXT_2;
2109 int max_word_len = 0;
2112 for (text_ptr = text; *text_ptr; text_ptr++)
2114 max_word_len = (*text_ptr != ' ' ? max_word_len + 1 : 0);
2116 if (max_word_len > MAX_REQUEST_LINE_FONT1_LEN)
2118 max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
2119 font_nr = FONT_LEVEL_NUMBER;
2126 /* disable deactivated drawing when quick-loading level tape recording */
2127 if (tape.playing && tape.deactivate_display)
2128 TapeDeactivateDisplayOff(TRUE);
2132 SetMouseCursor(CURSOR_DEFAULT);
2135 #if defined(NETWORK_AVALIABLE)
2136 /* pause network game while waiting for request to answer */
2137 if (options.network &&
2138 game_status == GAME_MODE_PLAYING &&
2139 req_state & REQUEST_WAIT_FOR_INPUT)
2140 SendToServer_PausePlaying();
2143 old_door_state = GetDoorState();
2145 /* simulate releasing mouse button over last gadget, if still pressed */
2147 HandleGadgets(-1, -1, 0);
2151 if (old_door_state & DOOR_OPEN_1)
2153 CloseDoor(DOOR_CLOSE_1);
2155 /* save old door content */
2156 BlitBitmap(bitmap_db_door, bitmap_db_door,
2157 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
2158 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
2161 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
2163 /* clear door drawing field */
2164 DrawBackground(DX, DY, DXSIZE, DYSIZE);
2166 /* force DOOR font on preview level */
2167 game_status = GAME_MODE_PSEUDO_DOOR;
2169 /* write text for request */
2170 for (ty = 0; ty < MAX_REQUEST_LINES; ty++)
2172 char text_line[max_request_line_len + 1];
2178 for (tl = 0, tx = 0; tx < max_request_line_len; tl++, tx++)
2181 if (!tc || tc == ' ')
2192 strncpy(text_line, text, tl);
2195 DrawText(DX + (DXSIZE - tl * getFontWidth(font_nr)) / 2,
2196 DY + 8 + ty * (getFontHeight(font_nr) + 2),
2197 text_line, font_nr);
2199 text += tl + (tc == ' ' ? 1 : 0);
2202 game_status = last_game_status; /* restore current game status */
2204 if (req_state & REQ_ASK)
2206 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
2207 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
2209 else if (req_state & REQ_CONFIRM)
2211 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
2213 else if (req_state & REQ_PLAYER)
2215 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
2216 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
2217 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
2218 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
2221 /* copy request gadgets to door backbuffer */
2222 BlitBitmap(drawto, bitmap_db_door,
2223 DX, DY, DXSIZE, DYSIZE,
2224 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2226 OpenDoor(DOOR_OPEN_1);
2232 if (!(req_state & REQUEST_WAIT_FOR_INPUT))
2234 SetDrawBackgroundMask(REDRAW_FIELD);
2239 if (game_status != GAME_MODE_MAIN)
2242 button_status = MB_RELEASED;
2244 request_gadget_id = -1;
2246 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
2249 SetMouseCursor(CURSOR_DEFAULT);
2262 case EVENT_BUTTONPRESS:
2263 case EVENT_BUTTONRELEASE:
2264 case EVENT_MOTIONNOTIFY:
2266 if (event.type == EVENT_MOTIONNOTIFY)
2268 if (!PointerInWindow(window))
2269 continue; /* window and pointer are on different screens */
2274 motion_status = TRUE;
2275 mx = ((MotionEvent *) &event)->x;
2276 my = ((MotionEvent *) &event)->y;
2280 motion_status = FALSE;
2281 mx = ((ButtonEvent *) &event)->x;
2282 my = ((ButtonEvent *) &event)->y;
2283 if (event.type == EVENT_BUTTONPRESS)
2284 button_status = ((ButtonEvent *) &event)->button;
2286 button_status = MB_RELEASED;
2289 /* this sets 'request_gadget_id' */
2290 HandleGadgets(mx, my, button_status);
2292 switch(request_gadget_id)
2294 case TOOL_CTRL_ID_YES:
2297 case TOOL_CTRL_ID_NO:
2300 case TOOL_CTRL_ID_CONFIRM:
2301 result = TRUE | FALSE;
2304 case TOOL_CTRL_ID_PLAYER_1:
2307 case TOOL_CTRL_ID_PLAYER_2:
2310 case TOOL_CTRL_ID_PLAYER_3:
2313 case TOOL_CTRL_ID_PLAYER_4:
2324 case EVENT_KEYPRESS:
2325 switch(GetEventKey((KeyEvent *)&event, TRUE))
2338 if (req_state & REQ_PLAYER)
2342 case EVENT_KEYRELEASE:
2343 ClearPlayerAction();
2347 HandleOtherEvents(&event);
2351 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2353 int joy = AnyJoystick();
2355 if (joy & JOY_BUTTON_1)
2357 else if (joy & JOY_BUTTON_2)
2363 /* don't eat all CPU time */
2367 if (game_status != GAME_MODE_MAIN)
2372 if (!(req_state & REQ_STAY_OPEN))
2374 CloseDoor(DOOR_CLOSE_1);
2376 if (((old_door_state & DOOR_OPEN_1) && !(req_state & REQ_STAY_CLOSED)) ||
2377 (req_state & REQ_REOPEN))
2378 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
2383 SetDrawBackgroundMask(REDRAW_FIELD);
2385 #if defined(NETWORK_AVALIABLE)
2386 /* continue network game after request */
2387 if (options.network &&
2388 game_status == GAME_MODE_PLAYING &&
2389 req_state & REQUEST_WAIT_FOR_INPUT)
2390 SendToServer_ContinuePlaying();
2394 /* restore deactivated drawing when quick-loading level tape recording */
2395 if (tape.playing && tape.deactivate_display)
2396 TapeDeactivateDisplayOn();
2402 unsigned int OpenDoor(unsigned int door_state)
2404 if (door_state & DOOR_COPY_BACK)
2406 if (door_state & DOOR_OPEN_1)
2407 BlitBitmap(bitmap_db_door, bitmap_db_door,
2408 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
2409 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2411 if (door_state & DOOR_OPEN_2)
2412 BlitBitmap(bitmap_db_door, bitmap_db_door,
2413 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY2, VXSIZE, VYSIZE,
2414 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2416 door_state &= ~DOOR_COPY_BACK;
2419 return MoveDoor(door_state);
2422 unsigned int CloseDoor(unsigned int door_state)
2424 unsigned int old_door_state = GetDoorState();
2426 if (!(door_state & DOOR_NO_COPY_BACK))
2428 if (old_door_state & DOOR_OPEN_1)
2429 BlitBitmap(backbuffer, bitmap_db_door,
2430 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2432 if (old_door_state & DOOR_OPEN_2)
2433 BlitBitmap(backbuffer, bitmap_db_door,
2434 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2436 door_state &= ~DOOR_NO_COPY_BACK;
2439 return MoveDoor(door_state);
2442 unsigned int GetDoorState()
2444 return MoveDoor(DOOR_GET_STATE);
2447 unsigned int SetDoorState(unsigned int door_state)
2449 return MoveDoor(door_state | DOOR_SET_STATE);
2452 unsigned int MoveDoor(unsigned int door_state)
2454 static int door1 = DOOR_OPEN_1;
2455 static int door2 = DOOR_CLOSE_2;
2456 unsigned long door_delay = 0;
2457 unsigned long door_delay_value;
2460 if (door_state == DOOR_GET_STATE)
2461 return(door1 | door2);
2463 if (door_state & DOOR_SET_STATE)
2465 if (door_state & DOOR_ACTION_1)
2466 door1 = door_state & DOOR_ACTION_1;
2467 if (door_state & DOOR_ACTION_2)
2468 door2 = door_state & DOOR_ACTION_2;
2470 return(door1 | door2);
2473 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2474 door_state &= ~DOOR_OPEN_1;
2475 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2476 door_state &= ~DOOR_CLOSE_1;
2477 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2478 door_state &= ~DOOR_OPEN_2;
2479 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2480 door_state &= ~DOOR_CLOSE_2;
2482 door_delay_value = (door_state & DOOR_ACTION_1 ? door_1.step_delay :
2485 if (setup.quick_doors)
2487 stepsize = 20; /* must be choosen to always draw last frame */
2488 door_delay_value = 0;
2491 StopSound(SND_DOOR_OPENING);
2492 StopSound(SND_DOOR_CLOSING);
2496 if (global.autoplay_leveldir)
2498 door_state |= DOOR_NO_DELAY;
2499 door_state &= ~DOOR_CLOSE_ALL;
2502 if (door_state & DOOR_ACTION)
2504 boolean door_1_done = !(door_state & DOOR_ACTION_1);
2505 boolean door_2_done = !(door_state & DOOR_ACTION_2);
2506 int start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2507 int end = (door_state & DOOR_ACTION_1 &&
2508 door_1.anim_mode == ANIM_VERTICAL ? DYSIZE : DXSIZE);
2511 if (!(door_state & DOOR_NO_DELAY) && !setup.quick_doors)
2513 /* opening door sound has priority over simultaneously closing door */
2514 if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
2515 PlaySoundStereo(SND_DOOR_OPENING, SOUND_MIDDLE);
2516 else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
2517 PlaySoundStereo(SND_DOOR_CLOSING, SOUND_MIDDLE);
2520 for (x = start; x <= end && !(door_1_done && door_2_done); x += stepsize)
2522 Bitmap *bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2523 GC gc = bitmap->stored_clip_gc;
2525 if (door_state & DOOR_ACTION_1)
2527 int a = MIN(x * door_1.step_offset, end);
2528 int i = (door_state & DOOR_OPEN_1 ? end - a : a);
2532 BlitBitmap(bitmap_db_door, drawto,
2533 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i / 2,
2534 DXSIZE, DYSIZE - i / 2, DX, DY);
2536 ClearRectangle(drawto, DX, DY + DYSIZE - i / 2, DXSIZE, i / 2);
2539 if (door_1.anim_mode == ANIM_HORIZONTAL && x <= DXSIZE)
2541 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
2542 int dst1_x = DX + DXSIZE - i, dst1_y = DY;
2543 int src2_x = DXSIZE - i, src2_y = DOOR_GFX_PAGEY1;
2544 int dst2_x = DX, dst2_y = DY;
2545 int width = i, height = DYSIZE;
2547 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2548 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2551 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2552 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2555 else if (door_1.anim_mode == ANIM_VERTICAL && x <= DYSIZE)
2557 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
2558 int dst1_x = DX, dst1_y = DY + DYSIZE - i;
2559 int src2_x = 0, src2_y = DOOR_GFX_PAGEY1 + DYSIZE - i;
2560 int dst2_x = DX, dst2_y = DY;
2561 int width = DXSIZE, height = i;
2563 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2564 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2567 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2568 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2571 else if (x <= DXSIZE) /* ANIM_DEFAULT */
2573 int j = (door_1.anim_mode == ANIM_DEFAULT ? (DXSIZE - i) / 3 : 0);
2575 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2576 BlitBitmapMasked(bitmap, drawto,
2577 DXSIZE, DOOR_GFX_PAGEY1, i, 77,
2578 DX + DXSIZE - i, DY + j);
2579 BlitBitmapMasked(bitmap, drawto,
2580 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
2581 DX + DXSIZE - i, DY + 140 + j);
2582 SetClipOrigin(bitmap, gc, DX - DXSIZE + i,
2583 DY - (DOOR_GFX_PAGEY1 + j));
2584 BlitBitmapMasked(bitmap, drawto,
2585 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
2587 BlitBitmapMasked(bitmap, drawto,
2588 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
2591 BlitBitmapMasked(bitmap, drawto,
2592 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2594 BlitBitmapMasked(bitmap, drawto,
2595 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2597 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2598 BlitBitmapMasked(bitmap, drawto,
2599 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2600 DX + DXSIZE - i, DY + 77 + j);
2601 BlitBitmapMasked(bitmap, drawto,
2602 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2603 DX + DXSIZE - i, DY + 203 + j);
2606 redraw_mask |= REDRAW_DOOR_1;
2607 door_1_done = (a == end);
2610 if (door_state & DOOR_ACTION_2)
2612 int a = MIN(x * door_2.step_offset, VXSIZE);
2613 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - a : a);
2617 BlitBitmap(bitmap_db_door, drawto,
2618 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i / 2,
2619 VXSIZE, VYSIZE - i / 2, VX, VY);
2621 ClearRectangle(drawto, VX, VY + VYSIZE - i / 2, VXSIZE, i / 2);
2624 if (door_2.anim_mode == ANIM_HORIZONTAL && x <= VXSIZE)
2626 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
2627 int dst1_x = VX + VXSIZE - i, dst1_y = VY;
2628 int src2_x = VXSIZE - i, src2_y = DOOR_GFX_PAGEY2;
2629 int dst2_x = VX, dst2_y = VY;
2630 int width = i, height = VYSIZE;
2632 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2633 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2636 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2637 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2640 else if (door_2.anim_mode == ANIM_VERTICAL && x <= VYSIZE)
2642 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
2643 int dst1_x = VX, dst1_y = VY + VYSIZE - i;
2644 int src2_x = 0, src2_y = DOOR_GFX_PAGEY2 + VYSIZE - i;
2645 int dst2_x = VX, dst2_y = VY;
2646 int width = VXSIZE, height = i;
2648 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2649 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2652 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2653 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2656 else if (x <= VXSIZE) /* ANIM_DEFAULT */
2658 int j = (door_2.anim_mode == ANIM_DEFAULT ? (VXSIZE - i) / 3 : 0);
2660 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2661 BlitBitmapMasked(bitmap, drawto,
2662 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
2663 VX + VXSIZE - i, VY + j);
2664 SetClipOrigin(bitmap, gc,
2665 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2666 BlitBitmapMasked(bitmap, drawto,
2667 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
2670 BlitBitmapMasked(bitmap, drawto,
2671 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2672 i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
2673 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2674 BlitBitmapMasked(bitmap, drawto,
2675 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2677 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2680 redraw_mask |= REDRAW_DOOR_2;
2681 door_2_done = (a == VXSIZE);
2686 if (game_status == GAME_MODE_MAIN)
2689 if (!(door_state & DOOR_NO_DELAY))
2690 WaitUntilDelayReached(&door_delay, door_delay_value);
2695 if (setup.quick_doors)
2697 StopSound(SND_DOOR_OPENING);
2698 StopSound(SND_DOOR_CLOSING);
2702 if (door_state & DOOR_ACTION_1)
2703 door1 = door_state & DOOR_ACTION_1;
2704 if (door_state & DOOR_ACTION_2)
2705 door2 = door_state & DOOR_ACTION_2;
2707 return (door1 | door2);
2710 void DrawSpecialEditorDoor()
2712 /* draw bigger toolbox window */
2713 BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
2714 DOOR_GFX_PAGEX7, 0, EXSIZE + 8, 8,
2716 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2717 EX - 4, VY - 4, EXSIZE + 8, EYSIZE - VYSIZE + 4,
2720 redraw_mask |= REDRAW_ALL;
2723 void UndrawSpecialEditorDoor()
2725 /* draw normal tape recorder window */
2726 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2727 EX - 4, EY - 12, EXSIZE + 8, EYSIZE - VYSIZE + 12,
2730 redraw_mask |= REDRAW_ALL;
2734 /* ---------- new tool button stuff ---------------------------------------- */
2736 /* graphic position values for tool buttons */
2737 #define TOOL_BUTTON_YES_XPOS 2
2738 #define TOOL_BUTTON_YES_YPOS 250
2739 #define TOOL_BUTTON_YES_GFX_YPOS 0
2740 #define TOOL_BUTTON_YES_XSIZE 46
2741 #define TOOL_BUTTON_YES_YSIZE 28
2742 #define TOOL_BUTTON_NO_XPOS 52
2743 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2744 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2745 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2746 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2747 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2748 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2749 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2750 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2751 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2752 #define TOOL_BUTTON_PLAYER_XSIZE 30
2753 #define TOOL_BUTTON_PLAYER_YSIZE 30
2754 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2755 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2756 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2757 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2758 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2759 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2760 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2761 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2762 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2763 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2764 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2765 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2766 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2767 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2768 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2769 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2770 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2771 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2772 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2773 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2782 } toolbutton_info[NUM_TOOL_BUTTONS] =
2785 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2786 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2787 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2792 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2793 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2794 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2799 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2800 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2801 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2802 TOOL_CTRL_ID_CONFIRM,
2806 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2807 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2808 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2809 TOOL_CTRL_ID_PLAYER_1,
2813 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2814 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2815 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2816 TOOL_CTRL_ID_PLAYER_2,
2820 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2821 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2822 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2823 TOOL_CTRL_ID_PLAYER_3,
2827 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2828 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2829 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2830 TOOL_CTRL_ID_PLAYER_4,
2835 void CreateToolButtons()
2839 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2841 Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2842 Bitmap *deco_bitmap = None;
2843 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2844 struct GadgetInfo *gi;
2845 unsigned long event_mask;
2846 int gd_xoffset, gd_yoffset;
2847 int gd_x1, gd_x2, gd_y;
2850 event_mask = GD_EVENT_RELEASED;
2852 gd_xoffset = toolbutton_info[i].xpos;
2853 gd_yoffset = toolbutton_info[i].ypos;
2854 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2855 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2856 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2858 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2860 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
2862 getMiniGraphicSource(PLAYER_NR_GFX(IMG_PLAYER_1, player_nr),
2863 &deco_bitmap, &deco_x, &deco_y);
2864 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2865 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2868 gi = CreateGadget(GDI_CUSTOM_ID, id,
2869 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2870 GDI_X, DX + toolbutton_info[i].x,
2871 GDI_Y, DY + toolbutton_info[i].y,
2872 GDI_WIDTH, toolbutton_info[i].width,
2873 GDI_HEIGHT, toolbutton_info[i].height,
2874 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2875 GDI_STATE, GD_BUTTON_UNPRESSED,
2876 GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
2877 GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
2878 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
2879 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2880 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2881 GDI_DECORATION_SHIFTING, 1, 1,
2882 GDI_EVENT_MASK, event_mask,
2883 GDI_CALLBACK_ACTION, HandleToolButtons,
2887 Error(ERR_EXIT, "cannot create gadget");
2889 tool_gadget[id] = gi;
2893 void FreeToolButtons()
2897 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2898 FreeGadget(tool_gadget[i]);
2901 static void UnmapToolButtons()
2905 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2906 UnmapGadget(tool_gadget[i]);
2909 static void HandleToolButtons(struct GadgetInfo *gi)
2911 request_gadget_id = gi->custom_id;
2919 boolean is_rnd_to_em_mapping; /* unique mapping EM <-> RND */
2920 boolean is_backside; /* backside of moving element */
2926 mapping_EM_to_RND_list[] =
2929 Xblank, TRUE, FALSE,
2933 Yacid_splash_eB, FALSE, TRUE,
2934 EL_ACID_SPLASH_RIGHT, -1, -1
2937 Yacid_splash_wB, FALSE, TRUE,
2938 EL_ACID_SPLASH_LEFT, -1, -1
2941 #ifdef EM_ENGINE_BAD_ROLL
2943 Xstone_force_e, FALSE, FALSE,
2944 EL_ROCK, -1, MV_BIT_RIGHT
2947 Xstone_force_w, FALSE, FALSE,
2948 EL_ROCK, -1, MV_BIT_LEFT
2951 Xnut_force_e, FALSE, FALSE,
2952 EL_NUT, -1, MV_BIT_RIGHT
2955 Xnut_force_w, FALSE, FALSE,
2956 EL_NUT, -1, MV_BIT_LEFT
2959 Xspring_force_e, FALSE, FALSE,
2960 EL_SPRING, -1, MV_BIT_RIGHT
2963 Xspring_force_w, FALSE, FALSE,
2964 EL_SPRING, -1, MV_BIT_LEFT
2967 Xemerald_force_e, FALSE, FALSE,
2968 EL_EMERALD, -1, MV_BIT_RIGHT
2971 Xemerald_force_w, FALSE, FALSE,
2972 EL_EMERALD, -1, MV_BIT_LEFT
2975 Xdiamond_force_e, FALSE, FALSE,
2976 EL_DIAMOND, -1, MV_BIT_RIGHT
2979 Xdiamond_force_w, FALSE, FALSE,
2980 EL_DIAMOND, -1, MV_BIT_LEFT
2983 Xbomb_force_e, FALSE, FALSE,
2984 EL_BOMB, -1, MV_BIT_RIGHT
2987 Xbomb_force_w, FALSE, FALSE,
2988 EL_BOMB, -1, MV_BIT_LEFT
2990 #endif /* EM_ENGINE_BAD_ROLL */
2993 Xstone, TRUE, FALSE,
2997 Xstone_pause, FALSE, FALSE,
3001 Xstone_fall, FALSE, FALSE,
3005 Ystone_s, FALSE, FALSE,
3006 EL_ROCK, ACTION_FALLING, -1
3009 Ystone_sB, FALSE, TRUE,
3010 EL_ROCK, ACTION_FALLING, -1
3013 Ystone_e, FALSE, FALSE,
3014 EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT
3017 Ystone_eB, FALSE, TRUE,
3018 EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT
3021 Ystone_w, FALSE, FALSE,
3022 EL_ROCK, ACTION_MOVING, MV_BIT_LEFT
3025 Ystone_wB, FALSE, TRUE,
3026 EL_ROCK, ACTION_MOVING, MV_BIT_LEFT
3033 Xnut_pause, FALSE, FALSE,
3037 Xnut_fall, FALSE, FALSE,
3041 Ynut_s, FALSE, FALSE,
3042 EL_NUT, ACTION_FALLING, -1
3045 Ynut_sB, FALSE, TRUE,
3046 EL_NUT, ACTION_FALLING, -1
3049 Ynut_e, FALSE, FALSE,
3050 EL_NUT, ACTION_MOVING, MV_BIT_RIGHT
3053 Ynut_eB, FALSE, TRUE,
3054 EL_NUT, ACTION_MOVING, MV_BIT_RIGHT
3057 Ynut_w, FALSE, FALSE,
3058 EL_NUT, ACTION_MOVING, MV_BIT_LEFT
3061 Ynut_wB, FALSE, TRUE,
3062 EL_NUT, ACTION_MOVING, MV_BIT_LEFT
3065 Xbug_n, TRUE, FALSE,
3069 Xbug_e, TRUE, FALSE,
3070 EL_BUG_RIGHT, -1, -1
3073 Xbug_s, TRUE, FALSE,
3077 Xbug_w, TRUE, FALSE,
3081 Xbug_gon, FALSE, FALSE,
3085 Xbug_goe, FALSE, FALSE,
3086 EL_BUG_RIGHT, -1, -1
3089 Xbug_gos, FALSE, FALSE,
3093 Xbug_gow, FALSE, FALSE,
3097 Ybug_n, FALSE, FALSE,
3098 EL_BUG, ACTION_MOVING, MV_BIT_UP
3101 Ybug_nB, FALSE, TRUE,
3102 EL_BUG, ACTION_MOVING, MV_BIT_UP
3105 Ybug_e, FALSE, FALSE,
3106 EL_BUG, ACTION_MOVING, MV_BIT_RIGHT
3109 Ybug_eB, FALSE, TRUE,
3110 EL_BUG, ACTION_MOVING, MV_BIT_RIGHT
3113 Ybug_s, FALSE, FALSE,
3114 EL_BUG, ACTION_MOVING, MV_BIT_DOWN
3117 Ybug_sB, FALSE, TRUE,
3118 EL_BUG, ACTION_MOVING, MV_BIT_DOWN
3121 Ybug_w, FALSE, FALSE,
3122 EL_BUG, ACTION_MOVING, MV_BIT_LEFT
3125 Ybug_wB, FALSE, TRUE,
3126 EL_BUG, ACTION_MOVING, MV_BIT_LEFT
3129 Ybug_w_n, FALSE, FALSE,
3130 EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_UP
3133 Ybug_n_e, FALSE, FALSE,
3134 EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3137 Ybug_e_s, FALSE, FALSE,
3138 EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
3141 Ybug_s_w, FALSE, FALSE,
3142 EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3145 Ybug_e_n, FALSE, FALSE,
3146 EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
3149 Ybug_s_e, FALSE, FALSE,
3150 EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3153 Ybug_w_s, FALSE, FALSE,
3154 EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
3157 Ybug_n_w, FALSE, FALSE,
3158 EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3161 Ybug_stone, FALSE, FALSE,
3162 EL_BUG, ACTION_SMASHED_BY_ROCK, -1
3165 Ybug_spring, FALSE, FALSE,
3166 EL_BUG, ACTION_SMASHED_BY_SPRING, -1
3169 Xtank_n, TRUE, FALSE,
3170 EL_SPACESHIP_UP, -1, -1
3173 Xtank_e, TRUE, FALSE,
3174 EL_SPACESHIP_RIGHT, -1, -1
3177 Xtank_s, TRUE, FALSE,
3178 EL_SPACESHIP_DOWN, -1, -1
3181 Xtank_w, TRUE, FALSE,
3182 EL_SPACESHIP_LEFT, -1, -1
3185 Xtank_gon, FALSE, FALSE,
3186 EL_SPACESHIP_UP, -1, -1
3189 Xtank_goe, FALSE, FALSE,
3190 EL_SPACESHIP_RIGHT, -1, -1
3193 Xtank_gos, FALSE, FALSE,
3194 EL_SPACESHIP_DOWN, -1, -1
3197 Xtank_gow, FALSE, FALSE,
3198 EL_SPACESHIP_LEFT, -1, -1
3201 Ytank_n, FALSE, FALSE,
3202 EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP
3205 Ytank_nB, FALSE, TRUE,
3206 EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP
3209 Ytank_e, FALSE, FALSE,
3210 EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT
3213 Ytank_eB, FALSE, TRUE,
3214 EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT
3217 Ytank_s, FALSE, FALSE,
3218 EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN
3221 Ytank_sB, FALSE, TRUE,
3222 EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN
3225 Ytank_w, FALSE, FALSE,
3226 EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT
3229 Ytank_wB, FALSE, TRUE,
3230 EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT
3233 Ytank_w_n, FALSE, FALSE,
3234 EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_UP
3237 Ytank_n_e, FALSE, FALSE,
3238 EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3241 Ytank_e_s, FALSE, FALSE,
3242 EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
3245 Ytank_s_w, FALSE, FALSE,
3246 EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3249 Ytank_e_n, FALSE, FALSE,
3250 EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
3253 Ytank_s_e, FALSE, FALSE,
3254 EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3257 Ytank_w_s, FALSE, FALSE,
3258 EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
3261 Ytank_n_w, FALSE, FALSE,
3262 EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3265 Ytank_stone, FALSE, FALSE,
3266 EL_SPACESHIP, ACTION_SMASHED_BY_ROCK, -1
3269 Ytank_spring, FALSE, FALSE,
3270 EL_SPACESHIP, ACTION_SMASHED_BY_SPRING, -1
3273 Xandroid, TRUE, FALSE,
3274 EL_EMC_ANDROID, ACTION_ACTIVE, -1
3277 Xandroid_1_n, FALSE, FALSE,
3278 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_UP
3281 Xandroid_2_n, FALSE, FALSE,
3282 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_UP
3285 Xandroid_1_e, FALSE, FALSE,
3286 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_RIGHT
3289 Xandroid_2_e, FALSE, FALSE,
3290 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_RIGHT
3293 Xandroid_1_w, FALSE, FALSE,
3294 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_LEFT
3297 Xandroid_2_w, FALSE, FALSE,
3298 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_LEFT
3301 Xandroid_1_s, FALSE, FALSE,
3302 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_DOWN
3305 Xandroid_2_s, FALSE, FALSE,
3306 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_DOWN
3309 Yandroid_n, FALSE, FALSE,
3310 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_UP
3313 Yandroid_nB, FALSE, TRUE,
3314 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_UP
3317 Yandroid_ne, FALSE, FALSE,
3318 EL_EMC_ANDROID, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3321 Yandroid_neB, FALSE, TRUE,
3322 EL_EMC_ANDROID, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3325 Yandroid_e, FALSE, FALSE,
3326 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_RIGHT
3329 Yandroid_eB, FALSE, TRUE,
3330 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_RIGHT
3333 Yandroid_se, FALSE, FALSE,
3334 EL_EMC_ANDROID, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3337 Yandroid_seB, FALSE, TRUE,
3338 EL_EMC_ANDROID, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3341 Yandroid_s, FALSE, FALSE,
3342 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_DOWN
3345 Yandroid_sB, FALSE, TRUE,
3346 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_DOWN
3349 Yandroid_sw, FALSE, FALSE,
3350 EL_EMC_ANDROID, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3353 Yandroid_swB, FALSE, TRUE,
3354 EL_EMC_ANDROID, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3357 Yandroid_w, FALSE, FALSE,
3358 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_LEFT
3361 Yandroid_wB, FALSE, TRUE,
3362 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_LEFT
3365 Yandroid_nw, FALSE, FALSE,
3366 EL_EMC_ANDROID, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3369 Yandroid_nwB, FALSE, TRUE,
3370 EL_EMC_ANDROID, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3373 Xspring, TRUE, FALSE,
3377 Xspring_pause, FALSE, FALSE,
3381 Xspring_e, FALSE, FALSE,
3385 Xspring_w, FALSE, FALSE,
3389 Xspring_fall, FALSE, FALSE,
3393 Yspring_s, FALSE, FALSE,
3394 EL_SPRING, ACTION_FALLING, -1
3397 Yspring_sB, FALSE, TRUE,
3398 EL_SPRING, ACTION_FALLING, -1
3401 Yspring_e, FALSE, FALSE,
3402 EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT
3405 Yspring_eB, FALSE, TRUE,
3406 EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT
3409 Yspring_w, FALSE, FALSE,
3410 EL_SPRING, ACTION_MOVING, MV_BIT_LEFT
3413 Yspring_wB, FALSE, TRUE,
3414 EL_SPRING, ACTION_MOVING, MV_BIT_LEFT
3417 Yspring_kill_e, FALSE, FALSE,
3418 EL_ROBOT, ACTION_SLURPED_BY_SPRING, MV_BIT_RIGHT
3421 Yspring_kill_eB, FALSE, TRUE,
3422 EL_ROBOT, ACTION_SLURPED_BY_SPRING, MV_BIT_RIGHT
3425 Yspring_kill_w, FALSE, FALSE,
3426 EL_ROBOT, ACTION_SLURPED_BY_SPRING, MV_BIT_LEFT
3429 Yspring_kill_wB, FALSE, TRUE,
3430 EL_ROBOT, ACTION_SLURPED_BY_SPRING, MV_BIT_LEFT
3433 Xeater_n, TRUE, FALSE,
3437 Xeater_e, FALSE, FALSE,
3441 Xeater_w, FALSE, FALSE,
3445 Xeater_s, FALSE, FALSE,
3449 Yeater_n, FALSE, FALSE,
3450 EL_YAMYAM, ACTION_MOVING, MV_BIT_UP
3453 Yeater_nB, FALSE, TRUE,
3454 EL_YAMYAM, ACTION_MOVING, MV_BIT_UP
3457 Yeater_e, FALSE, FALSE,
3458 EL_YAMYAM, ACTION_MOVING, MV_BIT_RIGHT
3461 Yeater_eB, FALSE, TRUE,
3462 EL_YAMYAM, ACTION_MOVING, MV_BIT_RIGHT
3465 Yeater_s, FALSE, FALSE,
3466 EL_YAMYAM, ACTION_MOVING, MV_BIT_DOWN
3469 Yeater_sB, FALSE, TRUE,
3470 EL_YAMYAM, ACTION_MOVING, MV_BIT_DOWN
3473 Yeater_w, FALSE, FALSE,
3474 EL_YAMYAM, ACTION_MOVING, MV_BIT_LEFT
3477 Yeater_wB, FALSE, TRUE,
3478 EL_YAMYAM, ACTION_MOVING, MV_BIT_LEFT
3481 Yeater_stone, FALSE, FALSE,
3482 EL_YAMYAM, ACTION_SMASHED_BY_ROCK, -1
3485 Yeater_spring, FALSE, FALSE,
3486 EL_YAMYAM, ACTION_SMASHED_BY_SPRING, -1
3489 Xalien, TRUE, FALSE,
3493 Xalien_pause, FALSE, FALSE,
3497 Yalien_n, FALSE, FALSE,
3498 EL_ROBOT, ACTION_MOVING, MV_BIT_UP
3501 Yalien_nB, FALSE, TRUE,
3502 EL_ROBOT, ACTION_MOVING, MV_BIT_UP
3505 Yalien_e, FALSE, FALSE,
3506 EL_ROBOT, ACTION_MOVING, MV_BIT_RIGHT
3509 Yalien_eB, FALSE, TRUE,
3510 EL_ROBOT, ACTION_MOVING, MV_BIT_RIGHT
3513 Yalien_s, FALSE, FALSE,
3514 EL_ROBOT, ACTION_MOVING, MV_BIT_DOWN
3517 Yalien_sB, FALSE, TRUE,
3518 EL_ROBOT, ACTION_MOVING, MV_BIT_DOWN
3521 Yalien_w, FALSE, FALSE,
3522 EL_ROBOT, ACTION_MOVING, MV_BIT_LEFT
3525 Yalien_wB, FALSE, TRUE,
3526 EL_ROBOT, ACTION_MOVING, MV_BIT_LEFT
3529 Yalien_stone, FALSE, FALSE,
3530 EL_ROBOT, ACTION_SMASHED_BY_ROCK, -1
3533 Yalien_spring, FALSE, FALSE,
3534 EL_ROBOT, ACTION_SMASHED_BY_SPRING, -1
3537 Xemerald, TRUE, FALSE,
3541 Xemerald_pause, FALSE, FALSE,
3545 Xemerald_fall, FALSE, FALSE,
3549 Xemerald_shine, FALSE, FALSE,
3550 EL_EMERALD, ACTION_TWINKLING, -1
3553 Yemerald_s, FALSE, FALSE,
3554 EL_EMERALD, ACTION_FALLING, -1
3557 Yemerald_sB, FALSE, TRUE,
3558 EL_EMERALD, ACTION_FALLING, -1
3561 Yemerald_e, FALSE, FALSE,
3562 EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT
3565 Yemerald_eB, FALSE, TRUE,
3566 EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT
3569 Yemerald_w, FALSE, FALSE,
3570 EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT
3573 Yemerald_wB, FALSE, TRUE,
3574 EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT
3577 Yemerald_eat, FALSE, FALSE,
3578 EL_EMERALD, ACTION_COLLECTING, -1
3581 Yemerald_stone, FALSE, FALSE,
3582 EL_NUT, ACTION_BREAKING, -1
3585 Xdiamond, TRUE, FALSE,
3589 Xdiamond_pause, FALSE, FALSE,
3593 Xdiamond_fall, FALSE, FALSE,
3597 Xdiamond_shine, FALSE, FALSE,
3598 EL_DIAMOND, ACTION_TWINKLING, -1
3601 Ydiamond_s, FALSE, FALSE,
3602 EL_DIAMOND, ACTION_FALLING, -1
3605 Ydiamond_sB, FALSE, TRUE,
3606 EL_DIAMOND, ACTION_FALLING, -1
3609 Ydiamond_e, FALSE, FALSE,
3610 EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT
3613 Ydiamond_eB, FALSE, TRUE,
3614 EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT
3617 Ydiamond_w, FALSE, FALSE,
3618 EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT
3621 Ydiamond_wB, FALSE, TRUE,
3622 EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT
3625 Ydiamond_eat, FALSE, FALSE,
3626 EL_DIAMOND, ACTION_COLLECTING, -1
3629 Ydiamond_stone, FALSE, FALSE,
3630 EL_DIAMOND, ACTION_SMASHED_BY_ROCK, -1
3633 Xdrip_fall, TRUE, FALSE,
3634 EL_AMOEBA_DROP, -1, -1
3637 Xdrip_stretch, FALSE, FALSE,
3638 EL_AMOEBA_DROP, ACTION_FALLING, -1
3641 Xdrip_stretchB, FALSE, TRUE,
3642 EL_AMOEBA_DROP, ACTION_FALLING, -1
3645 Xdrip_eat, FALSE, FALSE,
3646 EL_AMOEBA_DROP, ACTION_GROWING, -1
3649 Ydrip_s1, FALSE, FALSE,
3650 EL_AMOEBA_DROP, ACTION_FALLING, -1
3653 Ydrip_s1B, FALSE, TRUE,
3654 EL_AMOEBA_DROP, ACTION_FALLING, -1
3657 Ydrip_s2, FALSE, FALSE,
3658 EL_AMOEBA_DROP, ACTION_FALLING, -1
3661 Ydrip_s2B, FALSE, TRUE,
3662 EL_AMOEBA_DROP, ACTION_FALLING, -1
3669 Xbomb_pause, FALSE, FALSE,
3673 Xbomb_fall, FALSE, FALSE,
3677 Ybomb_s, FALSE, FALSE,
3678 EL_BOMB, ACTION_FALLING, -1
3681 Ybomb_sB, FALSE, TRUE,
3682 EL_BOMB, ACTION_FALLING, -1
3685 Ybomb_e, FALSE, FALSE,
3686 EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT
3689 Ybomb_eB, FALSE, TRUE,
3690 EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT
3693 Ybomb_w, FALSE, FALSE,
3694 EL_BOMB, ACTION_MOVING, MV_BIT_LEFT
3697 Ybomb_wB, FALSE, TRUE,
3698 EL_BOMB, ACTION_MOVING, MV_BIT_LEFT
3701 Ybomb_eat, FALSE, FALSE,
3702 EL_BOMB, ACTION_SMASHED_BY_ROCK, -1
3705 Xballoon, TRUE, FALSE,
3709 Yballoon_n, FALSE, FALSE,
3710 EL_BALLOON, ACTION_MOVING, MV_BIT_UP
3713 Yballoon_nB, FALSE, TRUE,
3714 EL_BALLOON, ACTION_MOVING, MV_BIT_UP
3717 Yballoon_e, FALSE, FALSE,
3718 EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT
3721 Yballoon_eB, FALSE, TRUE,
3722 EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT
3725 Yballoon_s, FALSE, FALSE,
3726 EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN
3729 Yballoon_sB, FALSE, TRUE,
3730 EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN
3733 Yballoon_w, FALSE, FALSE,
3734 EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT
3737 Yballoon_wB, FALSE, TRUE,
3738 EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT
3741 Xgrass, TRUE, FALSE,
3742 EL_EMC_GRASS, -1, -1
3745 Ygrass_nB, FALSE, TRUE,
3746 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_UP
3749 Ygrass_eB, FALSE, TRUE,
3750 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_RIGHT
3753 Ygrass_sB, FALSE, TRUE,
3754 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_DOWN
3757 Ygrass_wB, FALSE, TRUE,
3758 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_LEFT
3765 Ydirt_nB, FALSE, TRUE,
3766 EL_SAND, ACTION_DIGGING, MV_BIT_UP
3769 Ydirt_eB, FALSE, TRUE,
3770 EL_SAND, ACTION_DIGGING, MV_BIT_RIGHT
3773 Ydirt_sB, FALSE, TRUE,
3774 EL_SAND, ACTION_DIGGING, MV_BIT_DOWN
3777 Ydirt_wB, FALSE, TRUE,
3778 EL_SAND, ACTION_DIGGING, MV_BIT_LEFT
3781 Xacid_ne, TRUE, FALSE,
3782 EL_ACID_POOL_TOPRIGHT, -1, -1
3785 Xacid_se, TRUE, FALSE,
3786 EL_ACID_POOL_BOTTOMRIGHT, -1, -1
3789 Xacid_s, TRUE, FALSE,
3790 EL_ACID_POOL_BOTTOM, -1, -1
3793 Xacid_sw, TRUE, FALSE,
3794 EL_ACID_POOL_BOTTOMLEFT, -1, -1
3797 Xacid_nw, TRUE, FALSE,
3798 EL_ACID_POOL_TOPLEFT, -1, -1
3801 Xacid_1, TRUE, FALSE,
3805 Xacid_2, FALSE, FALSE,
3809 Xacid_3, FALSE, FALSE,
3813 Xacid_4, FALSE, FALSE,
3817 Xacid_5, FALSE, FALSE,
3821 Xacid_6, FALSE, FALSE,
3825 Xacid_7, FALSE, FALSE,
3829 Xacid_8, FALSE, FALSE,
3833 Xball_1, TRUE, FALSE,
3834 EL_EMC_MAGIC_BALL, -1, -1
3837 Xball_1B, FALSE, TRUE,
3838 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
3841 Xball_2, FALSE, FALSE,
3842 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
3845 Xball_2B, FALSE, TRUE,
3846 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
3849 Yball_eat, FALSE, FALSE,
3850 EL_EMC_MAGIC_BALL, ACTION_DROPPING, -1
3853 Xgrow_ns, TRUE, FALSE,
3854 EL_EXPANDABLE_WALL_VERTICAL, -1, -1
3857 Ygrow_ns_eat, FALSE, FALSE,
3858 EL_EXPANDABLE_WALL_VERTICAL, ACTION_GROWING, -1
3861 Xgrow_ew, TRUE, FALSE,
3862 EL_EXPANDABLE_WALL_HORIZONTAL, -1, -1
3865 Ygrow_ew_eat, FALSE, FALSE,
3866 EL_EXPANDABLE_WALL_HORIZONTAL, ACTION_GROWING, -1
3869 Xwonderwall, TRUE, FALSE,
3870 EL_MAGIC_WALL, -1, -1
3873 XwonderwallB, FALSE, FALSE,
3874 EL_MAGIC_WALL, ACTION_ACTIVE, -1
3877 Xamoeba_1, TRUE, FALSE,
3878 EL_AMOEBA_DRY, ACTION_OTHER, -1
3881 Xamoeba_2, FALSE, FALSE,
3882 EL_AMOEBA_DRY, ACTION_OTHER, -1
3885 Xamoeba_3, FALSE, FALSE,
3886 EL_AMOEBA_DRY, ACTION_OTHER, -1
3889 Xamoeba_4, FALSE, FALSE,
3890 EL_AMOEBA_DRY, ACTION_OTHER, -1
3893 Xamoeba_5, FALSE, FALSE,
3894 EL_AMOEBA_WET, ACTION_OTHER, -1
3897 Xamoeba_6, FALSE, FALSE,
3898 EL_AMOEBA_WET, ACTION_OTHER, -1
3901 Xamoeba_7, FALSE, FALSE,
3902 EL_AMOEBA_WET, ACTION_OTHER, -1
3905 Xamoeba_8, FALSE, FALSE,
3906 EL_AMOEBA_WET, ACTION_OTHER, -1
3909 Xdoor_1, TRUE, FALSE,
3910 EL_EM_GATE_1, -1, -1
3913 Xdoor_2, TRUE, FALSE,
3914 EL_EM_GATE_2, -1, -1
3917 Xdoor_3, TRUE, FALSE,
3918 EL_EM_GATE_3, -1, -1
3921 Xdoor_4, TRUE, FALSE,
3922 EL_EM_GATE_4, -1, -1
3925 Xdoor_5, TRUE, FALSE,
3926 EL_EM_GATE_5, -1, -1
3929 Xdoor_6, TRUE, FALSE,
3930 EL_EM_GATE_6, -1, -1
3933 Xdoor_7, TRUE, FALSE,
3934 EL_EM_GATE_7, -1, -1
3937 Xdoor_8, TRUE, FALSE,
3938 EL_EM_GATE_8, -1, -1
3941 Xkey_1, TRUE, FALSE,
3945 Xkey_2, TRUE, FALSE,
3949 Xkey_3, TRUE, FALSE,
3953 Xkey_4, TRUE, FALSE,
3957 Xkey_5, TRUE, FALSE,
3961 Xkey_6, TRUE, FALSE,
3965 Xkey_7, TRUE, FALSE,
3969 Xkey_8, TRUE, FALSE,
3973 Xwind_n, TRUE, FALSE,
3974 EL_BALLOON_SWITCH_UP, -1, -1
3977 Xwind_e, TRUE, FALSE,
3978 EL_BALLOON_SWITCH_RIGHT, -1, -1
3981 Xwind_s, TRUE, FALSE,
3982 EL_BALLOON_SWITCH_DOWN, -1, -1
3985 Xwind_w, TRUE, FALSE,
3986 EL_BALLOON_SWITCH_LEFT, -1, -1
3989 Xwind_nesw, TRUE, FALSE,
3990 EL_BALLOON_SWITCH_ANY, -1, -1
3993 Xwind_stop, TRUE, FALSE,
3994 EL_BALLOON_SWITCH_NONE, -1, -1
3998 EL_EXIT_CLOSED, -1, -1
4001 Xexit_1, TRUE, FALSE,
4002 EL_EXIT_OPEN, -1, -1
4005 Xexit_2, FALSE, FALSE,
4006 EL_EXIT_OPEN, -1, -1
4009 Xexit_3, FALSE, FALSE,
4010 EL_EXIT_OPEN, -1, -1
4013 Xdynamite, TRUE, FALSE,
4017 Ydynamite_eat, FALSE, FALSE,
4018 EL_DYNAMITE, ACTION_COLLECTING, -1
4021 Xdynamite_1, TRUE, FALSE,
4022 EL_DYNAMITE_ACTIVE, -1, -1
4025 Xdynamite_2, FALSE, FALSE,
4026 EL_DYNAMITE_ACTIVE, -1, -1
4029 Xdynamite_3, FALSE, FALSE,
4030 EL_DYNAMITE_ACTIVE, -1, -1
4033 Xdynamite_4, FALSE, FALSE,
4034 EL_DYNAMITE_ACTIVE, -1, -1
4037 Xbumper, TRUE, FALSE,
4038 EL_EMC_SPRING_BUMPER, -1, -1
4041 XbumperB, FALSE, FALSE,
4042 EL_EMC_SPRING_BUMPER, ACTION_ACTIVE, -1
4045 Xwheel, TRUE, FALSE,
4046 EL_ROBOT_WHEEL, -1, -1
4049 XwheelB, FALSE, FALSE,
4050 EL_ROBOT_WHEEL, ACTION_ACTIVE, -1
4053 Xswitch, TRUE, FALSE,
4054 EL_EMC_MAGIC_BALL_SWITCH, -1, -1
4057 XswitchB, FALSE, FALSE,
4058 EL_EMC_MAGIC_BALL_SWITCH, ACTION_ACTIVE, -1
4062 EL_QUICKSAND_EMPTY, -1, -1
4065 Xsand_stone, TRUE, FALSE,
4066 EL_QUICKSAND_FULL, -1, -1
4069 Xsand_stonein_1, FALSE, FALSE,
4070 EL_ROCK, ACTION_FILLING, -1
4073 Xsand_stonein_2, FALSE, FALSE,
4074 EL_ROCK, ACTION_FILLING, -1
4077 Xsand_stonein_3, FALSE, FALSE,
4078 EL_ROCK, ACTION_FILLING, -1
4081 Xsand_stonein_4, FALSE, FALSE,
4082 EL_ROCK, ACTION_FILLING, -1
4085 Xsand_stonesand_1, FALSE, FALSE,
4086 EL_QUICKSAND_FULL, -1, -1
4089 Xsand_stonesand_2, FALSE, FALSE,
4090 EL_QUICKSAND_FULL, -1, -1
4093 Xsand_stonesand_3, FALSE, FALSE,
4094 EL_QUICKSAND_FULL, -1, -1
4097 Xsand_stonesand_4, FALSE, FALSE,
4098 EL_QUICKSAND_FULL, -1, -1
4101 Xsand_stoneout_1, FALSE, FALSE,
4102 EL_ROCK, ACTION_EMPTYING, -1
4105 Xsand_stoneout_2, FALSE, FALSE,
4106 EL_ROCK, ACTION_EMPTYING, -1
4109 Xsand_sandstone_1, FALSE, FALSE,
4110 EL_QUICKSAND_FULL, -1, -1
4113 Xsand_sandstone_2, FALSE, FALSE,
4114 EL_QUICKSAND_FULL, -1, -1
4117 Xsand_sandstone_3, FALSE, FALSE,
4118 EL_QUICKSAND_FULL, -1, -1
4121 Xsand_sandstone_4, FALSE, FALSE,
4122 EL_QUICKSAND_FULL, -1, -1
4125 Xplant, TRUE, FALSE,
4126 EL_EMC_PLANT, -1, -1
4129 Yplant, FALSE, FALSE,
4130 EL_EMC_PLANT, -1, -1
4133 Xlenses, TRUE, FALSE,
4134 EL_EMC_LENSES, -1, -1
4137 Xmagnify, TRUE, FALSE,
4138 EL_EMC_MAGNIFIER, -1, -1
4141 Xdripper, TRUE, FALSE,
4142 EL_EMC_DRIPPER, -1, -1
4145 XdripperB, FALSE, FALSE,
4146 EL_EMC_DRIPPER, ACTION_ACTIVE, -1
4149 Xfake_blank, TRUE, FALSE,
4150 EL_INVISIBLE_WALL, -1, -1
4153 Xfake_blankB, FALSE, FALSE,
4154 EL_INVISIBLE_WALL, ACTION_ACTIVE, -1
4157 Xfake_grass, TRUE, FALSE,
4158 EL_EMC_FAKE_GRASS, -1, -1
4161 Xfake_grassB, FALSE, FALSE,
4162 EL_EMC_FAKE_GRASS, ACTION_ACTIVE, -1
4165 Xfake_door_1, TRUE, FALSE,
4166 EL_EM_GATE_1_GRAY, -1, -1
4169 Xfake_door_2, TRUE, FALSE,
4170 EL_EM_GATE_2_GRAY, -1, -1
4173 Xfake_door_3, TRUE, FALSE,
4174 EL_EM_GATE_3_GRAY, -1, -1
4177 Xfake_door_4, TRUE, FALSE,
4178 EL_EM_GATE_4_GRAY, -1, -1
4181 Xfake_door_5, TRUE, FALSE,
4182 EL_EM_GATE_5_GRAY, -1, -1
4185 Xfake_door_6, TRUE, FALSE,
4186 EL_EM_GATE_6_GRAY, -1, -1
4189 Xfake_door_7, TRUE, FALSE,
4190 EL_EM_GATE_7_GRAY, -1, -1
4193 Xfake_door_8, TRUE, FALSE,
4194 EL_EM_GATE_8_GRAY, -1, -1
4197 Xsteel_1, TRUE, FALSE,
4198 EL_STEELWALL, -1, -1
4201 Xsteel_2, TRUE, FALSE,
4202 EL_EMC_STEELWALL_2, -1, -1
4205 Xsteel_3, TRUE, FALSE,
4206 EL_EMC_STEELWALL_3, -1, -1
4209 Xsteel_4, TRUE, FALSE,
4210 EL_EMC_STEELWALL_4, -1, -1
4213 Xwall_1, TRUE, FALSE,
4217 Xwall_2, TRUE, FALSE,
4218 EL_EMC_WALL_14, -1, -1
4221 Xwall_3, TRUE, FALSE,
4222 EL_EMC_WALL_15, -1, -1
4225 Xwall_4, TRUE, FALSE,
4226 EL_EMC_WALL_16, -1, -1
4229 Xround_wall_1, TRUE, FALSE,
4230 EL_WALL_SLIPPERY, -1, -1
4233 Xround_wall_2, TRUE, FALSE,
4234 EL_EMC_WALL_SLIPPERY_2, -1, -1
4237 Xround_wall_3, TRUE, FALSE,
4238 EL_EMC_WALL_SLIPPERY_3, -1, -1
4241 Xround_wall_4, TRUE, FALSE,
4242 EL_EMC_WALL_SLIPPERY_4, -1, -1
4245 Xdecor_1, TRUE, FALSE,
4246 EL_EMC_WALL_8, -1, -1
4249 Xdecor_2, TRUE, FALSE,
4250 EL_EMC_WALL_6, -1, -1
4253 Xdecor_3, TRUE, FALSE,
4254 EL_EMC_WALL_4, -1, -1
4257 Xdecor_4, TRUE, FALSE,
4258 EL_EMC_WALL_7, -1, -1
4261 Xdecor_5, TRUE, FALSE,
4262 EL_EMC_WALL_5, -1, -1
4265 Xdecor_6, TRUE, FALSE,
4266 EL_EMC_WALL_9, -1, -1
4269 Xdecor_7, TRUE, FALSE,
4270 EL_EMC_WALL_10, -1, -1
4273 Xdecor_8, TRUE, FALSE,
4274 EL_EMC_WALL_1, -1, -1
4277 Xdecor_9, TRUE, FALSE,
4278 EL_EMC_WALL_2, -1, -1
4281 Xdecor_10, TRUE, FALSE,
4282 EL_EMC_WALL_3, -1, -1
4285 Xdecor_11, TRUE, FALSE,
4286 EL_EMC_WALL_11, -1, -1
4289 Xdecor_12, TRUE, FALSE,
4290 EL_EMC_WALL_12, -1, -1
4293 Xalpha_0, TRUE, FALSE,
4294 EL_CHAR('0'), -1, -1
4297 Xalpha_1, TRUE, FALSE,
4298 EL_CHAR('1'), -1, -1
4301 Xalpha_2, TRUE, FALSE,
4302 EL_CHAR('2'), -1, -1
4305 Xalpha_3, TRUE, FALSE,
4306 EL_CHAR('3'), -1, -1
4309 Xalpha_4, TRUE, FALSE,
4310 EL_CHAR('4'), -1, -1
4313 Xalpha_5, TRUE, FALSE,
4314 EL_CHAR('5'), -1, -1
4317 Xalpha_6, TRUE, FALSE,
4318 EL_CHAR('6'), -1, -1
4321 Xalpha_7, TRUE, FALSE,
4322 EL_CHAR('7'), -1, -1
4325 Xalpha_8, TRUE, FALSE,
4326 EL_CHAR('8'), -1, -1
4329 Xalpha_9, TRUE, FALSE,
4330 EL_CHAR('9'), -1, -1
4333 Xalpha_excla, TRUE, FALSE,
4334 EL_CHAR('!'), -1, -1
4337 Xalpha_quote, TRUE, FALSE,
4338 EL_CHAR('"'), -1, -1
4341 Xalpha_comma, TRUE, FALSE,
4342 EL_CHAR(','), -1, -1
4345 Xalpha_minus, TRUE, FALSE,
4346 EL_CHAR('-'), -1, -1
4349 Xalpha_perio, TRUE, FALSE,
4350 EL_CHAR('.'), -1, -1
4353 Xalpha_colon, TRUE, FALSE,
4354 EL_CHAR(':'), -1, -1
4357 Xalpha_quest, TRUE, FALSE,
4358 EL_CHAR('?'), -1, -1
4361 Xalpha_a, TRUE, FALSE,
4362 EL_CHAR('A'), -1, -1
4365 Xalpha_b, TRUE, FALSE,
4366 EL_CHAR('B'), -1, -1
4369 Xalpha_c, TRUE, FALSE,
4370 EL_CHAR('C'), -1, -1
4373 Xalpha_d, TRUE, FALSE,
4374 EL_CHAR('D'), -1, -1
4377 Xalpha_e, TRUE, FALSE,
4378 EL_CHAR('E'), -1, -1
4381 Xalpha_f, TRUE, FALSE,
4382 EL_CHAR('F'), -1, -1
4385 Xalpha_g, TRUE, FALSE,
4386 EL_CHAR('G'), -1, -1
4389 Xalpha_h, TRUE, FALSE,
4390 EL_CHAR('H'), -1, -1
4393 Xalpha_i, TRUE, FALSE,
4394 EL_CHAR('I'), -1, -1
4397 Xalpha_j, TRUE, FALSE,
4398 EL_CHAR('J'), -1, -1
4401 Xalpha_k, TRUE, FALSE,
4402 EL_CHAR('K'), -1, -1
4405 Xalpha_l, TRUE, FALSE,
4406 EL_CHAR('L'), -1, -1
4409 Xalpha_m, TRUE, FALSE,
4410 EL_CHAR('M'), -1, -1
4413 Xalpha_n, TRUE, FALSE,
4414 EL_CHAR('N'), -1, -1
4417 Xalpha_o, TRUE, FALSE,
4418 EL_CHAR('O'), -1, -1
4421 Xalpha_p, TRUE, FALSE,
4422 EL_CHAR('P'), -1, -1
4425 Xalpha_q, TRUE, FALSE,
4426 EL_CHAR('Q'), -1, -1
4429 Xalpha_r, TRUE, FALSE,
4430 EL_CHAR('R'), -1, -1
4433 Xalpha_s, TRUE, FALSE,
4434 EL_CHAR('S'), -1, -1
4437 Xalpha_t, TRUE, FALSE,
4438 EL_CHAR('T'), -1, -1
4441 Xalpha_u, TRUE, FALSE,
4442 EL_CHAR('U'), -1, -1
4445 Xalpha_v, TRUE, FALSE,
4446 EL_CHAR('V'), -1, -1
4449 Xalpha_w, TRUE, FALSE,
4450 EL_CHAR('W'), -1, -1
4453 Xalpha_x, TRUE, FALSE,
4454 EL_CHAR('X'), -1, -1
4457 Xalpha_y, TRUE, FALSE,
4458 EL_CHAR('Y'), -1, -1
4461 Xalpha_z, TRUE, FALSE,
4462 EL_CHAR('Z'), -1, -1
4465 Xalpha_arrow_e, TRUE, FALSE,
4466 EL_CHAR('>'), -1, -1
4469 Xalpha_arrow_w, TRUE, FALSE,
4470 EL_CHAR('<'), -1, -1
4473 Xalpha_copyr, TRUE, FALSE,
4474 EL_CHAR('©'), -1, -1
4477 Xalpha_copyr, TRUE, FALSE,
4478 EL_CHAR('©'), -1, -1
4482 Xboom_bug, FALSE, FALSE,
4483 EL_BUG, ACTION_EXPLODING, -1
4486 Xboom_bomb, FALSE, FALSE,
4487 EL_BOMB, ACTION_EXPLODING, -1
4490 Xboom_android, FALSE, FALSE,
4491 EL_EMC_ANDROID, ACTION_OTHER, -1
4494 Xboom_1, FALSE, FALSE,
4495 EL_DEFAULT, ACTION_EXPLODING, -1
4498 Xboom_2, FALSE, FALSE,
4499 EL_DEFAULT, ACTION_EXPLODING, -1
4502 Znormal, FALSE, FALSE,
4506 Zdynamite, FALSE, FALSE,
4510 Zplayer, FALSE, FALSE,
4514 ZBORDER, FALSE, FALSE,
4524 int map_element_RND_to_EM(int element_rnd)
4526 static unsigned short mapping_RND_to_EM[NUM_FILE_ELEMENTS];
4527 static boolean mapping_initialized = FALSE;
4529 if (!mapping_initialized)
4533 /* return "Xalpha_quest" for all undefined elements in mapping array */
4534 for (i = 0; i < NUM_FILE_ELEMENTS; i++)
4535 mapping_RND_to_EM[i] = Xalpha_quest;
4537 for (i = 0; mapping_EM_to_RND_list[i].element_em != -1; i++)
4538 if (mapping_EM_to_RND_list[i].is_rnd_to_em_mapping)
4539 mapping_RND_to_EM[mapping_EM_to_RND_list[i].element_rnd] =
4540 mapping_EM_to_RND_list[i].element_em;
4542 mapping_initialized = TRUE;
4545 if (element_rnd >= 0 && element_rnd < NUM_FILE_ELEMENTS)
4546 return mapping_RND_to_EM[element_rnd];
4548 Error(ERR_WARN, "invalid RND level element %d", element_rnd);
4553 int map_element_EM_to_RND(int element_em)
4555 static unsigned short mapping_EM_to_RND[TILE_MAX];
4556 static boolean mapping_initialized = FALSE;
4558 if (!mapping_initialized)
4562 /* return "EL_UNKNOWN" for all undefined elements in mapping array */
4563 for (i = 0; i < TILE_MAX; i++)
4564 mapping_EM_to_RND[i] = EL_UNKNOWN;
4566 for (i = 0; mapping_EM_to_RND_list[i].element_em != -1; i++)
4567 mapping_EM_to_RND[mapping_EM_to_RND_list[i].element_em] =
4568 mapping_EM_to_RND_list[i].element_rnd;
4570 mapping_initialized = TRUE;
4573 if (element_em >= 0 && element_em < TILE_MAX)
4574 return mapping_EM_to_RND[element_em];
4576 Error(ERR_WARN, "invalid EM level element %d", element_em);
4583 int map_element_RND_to_EM(int element_rnd)
4585 static unsigned short mapping_RND_to_EM[NUM_FILE_ELEMENTS];
4586 static boolean mapping_initialized = FALSE;
4593 mapping_RND_to_EM_list[] =
4595 { Xblank, EL_EMPTY },
4596 { Xstone, EL_ROCK },
4598 { Xbug_n, EL_BUG_UP },
4599 { Xbug_e, EL_BUG_RIGHT },
4600 { Xbug_s, EL_BUG_DOWN },
4601 { Xbug_w, EL_BUG_LEFT },
4602 { Xtank_n, EL_SPACESHIP_UP },
4603 { Xtank_e, EL_SPACESHIP_RIGHT },
4604 { Xtank_s, EL_SPACESHIP_DOWN },
4605 { Xtank_w, EL_SPACESHIP_LEFT },
4606 { Xandroid, EL_EMC_ANDROID },
4607 { Xandroid_1_n, EL_EMC_ANDROID_UP },
4608 { Xandroid_1_e, EL_EMC_ANDROID_RIGHT },
4609 { Xandroid_1_w, EL_EMC_ANDROID_LEFT },
4610 { Xandroid_1_s, EL_EMC_ANDROID_DOWN },
4611 { Xspring, EL_SPRING },
4612 { Xeater_n, EL_YAMYAM },
4613 { Xalien, EL_ROBOT },
4614 { Xemerald, EL_EMERALD },
4615 { Xdiamond, EL_DIAMOND },
4616 { Xdrip_fall, EL_AMOEBA_DROP },
4618 { Xballoon, EL_BALLOON },
4619 { Xgrass, EL_EMC_GRASS },
4621 { Xacid_ne, EL_ACID_POOL_TOPRIGHT },
4622 { Xacid_se, EL_ACID_POOL_BOTTOMRIGHT },
4623 { Xacid_s, EL_ACID_POOL_BOTTOM },
4624 { Xacid_sw, EL_ACID_POOL_BOTTOMLEFT },
4625 { Xacid_nw, EL_ACID_POOL_TOPLEFT },
4626 { Xacid_1, EL_ACID },
4627 { Xball_1, EL_EMC_MAGIC_BALL },
4628 { Xgrow_ns, EL_EMC_GROW },
4629 { Xwonderwall, EL_MAGIC_WALL },
4630 { Xamoeba_1, EL_AMOEBA_WET },
4631 { Xdoor_1, EL_EM_GATE_1 },
4632 { Xdoor_2, EL_EM_GATE_2 },
4633 { Xdoor_3, EL_EM_GATE_3 },
4634 { Xdoor_4, EL_EM_GATE_4 },
4635 { Xdoor_5, EL_EMC_GATE_5 },
4636 { Xdoor_6, EL_EMC_GATE_6 },
4637 { Xdoor_7, EL_EMC_GATE_7 },
4638 { Xdoor_8, EL_EMC_GATE_8 },
4639 { Xkey_1, EL_EM_KEY_1 },
4640 { Xkey_2, EL_EM_KEY_2 },
4641 { Xkey_3, EL_EM_KEY_3 },
4642 { Xkey_4, EL_EM_KEY_4 },
4643 { Xkey_5, EL_EMC_KEY_5 },
4644 { Xkey_6, EL_EMC_KEY_6 },
4645 { Xkey_7, EL_EMC_KEY_7 },
4646 { Xkey_8, EL_EMC_KEY_8 },
4647 { Xwind_n, EL_BALLOON_SWITCH_UP },
4648 { Xwind_e, EL_BALLOON_SWITCH_RIGHT },
4649 { Xwind_s, EL_BALLOON_SWITCH_DOWN },
4650 { Xwind_w, EL_BALLOON_SWITCH_LEFT },
4651 { Xwind_nesw, EL_BALLOON_SWITCH_ANY },
4652 { Xwind_stop, EL_BALLOON_SWITCH_NONE },
4653 { Xexit, EL_EXIT_CLOSED },
4654 { Xexit_1, EL_EXIT_OPEN },
4655 { Xdynamite, EL_DYNAMITE },
4656 { Xdynamite_1, EL_DYNAMITE_ACTIVE },
4657 { Xbumper, EL_EMC_BUMPER },
4658 { Xwheel, EL_ROBOT_WHEEL },
4659 { Xswitch, EL_UNKNOWN },
4660 { Xsand, EL_QUICKSAND_EMPTY },
4661 { Xsand_stone, EL_QUICKSAND_FULL },
4662 { Xplant, EL_EMC_PLANT },
4663 { Xlenses, EL_EMC_LENSES },
4664 { Xmagnify, EL_EMC_MAGNIFIER },
4665 { Xdripper, EL_UNKNOWN },
4666 { Xfake_blank, EL_INVISIBLE_WALL },
4667 { Xfake_grass, EL_INVISIBLE_SAND },
4668 { Xfake_door_1, EL_EM_GATE_1_GRAY },
4669 { Xfake_door_2, EL_EM_GATE_2_GRAY },
4670 { Xfake_door_3, EL_EM_GATE_3_GRAY },
4671 { Xfake_door_4, EL_EM_GATE_4_GRAY },
4672 { Xfake_door_5, EL_EMC_GATE_5_GRAY },
4673 { Xfake_door_6, EL_EMC_GATE_6_GRAY },
4674 { Xfake_door_7, EL_EMC_GATE_7_GRAY },
4675 { Xfake_door_8, EL_EMC_GATE_8_GRAY },
4676 { Xsteel_1, EL_STEELWALL },
4677 { Xsteel_2, EL_UNKNOWN },
4678 { Xsteel_3, EL_EMC_STEELWALL_1 },
4679 { Xsteel_4, EL_UNKNOWN },
4680 { Xwall_1, EL_WALL },
4681 { Xwall_2, EL_UNKNOWN },
4682 { Xwall_3, EL_UNKNOWN },
4683 { Xwall_4, EL_UNKNOWN },
4684 { Xround_wall_1, EL_WALL_SLIPPERY },
4685 { Xround_wall_2, EL_UNKNOWN },
4686 { Xround_wall_3, EL_UNKNOWN },
4687 { Xround_wall_4, EL_UNKNOWN },
4688 { Xdecor_1, EL_UNKNOWN },
4689 { Xdecor_2, EL_EMC_WALL_6 },
4690 { Xdecor_3, EL_EMC_WALL_4 },
4691 { Xdecor_4, EL_EMC_WALL_5 },
4692 { Xdecor_5, EL_EMC_WALL_7 },
4693 { Xdecor_6, EL_EMC_WALL_8 },
4694 { Xdecor_7, EL_UNKNOWN },
4695 { Xdecor_8, EL_EMC_WALL_1 },
4696 { Xdecor_9, EL_EMC_WALL_2 },
4697 { Xdecor_10, EL_EMC_WALL_3 },
4698 { Xdecor_11, EL_UNKNOWN },
4699 { Xdecor_12, EL_UNKNOWN },
4700 { Xalpha_0, EL_CHAR('0') },
4701 { Xalpha_1, EL_CHAR('1') },
4702 { Xalpha_2, EL_CHAR('2') },
4703 { Xalpha_3, EL_CHAR('3') },
4704 { Xalpha_4, EL_CHAR('4') },
4705 { Xalpha_5, EL_CHAR('5') },
4706 { Xalpha_6, EL_CHAR('6') },
4707 { Xalpha_7, EL_CHAR('7') },
4708 { Xalpha_8, EL_CHAR('8') },
4709 { Xalpha_9, EL_CHAR('9') },
4710 { Xalpha_excla, EL_CHAR('!') },
4711 { Xalpha_quote, EL_CHAR('"') },
4712 { Xalpha_comma, EL_CHAR(',') },
4713 { Xalpha_minus, EL_CHAR('-') },
4714 { Xalpha_perio, EL_CHAR('.') },
4715 { Xalpha_colon, EL_CHAR(':') },
4716 { Xalpha_quest, EL_CHAR('?') },
4717 { Xalpha_a, EL_CHAR('A') },
4718 { Xalpha_b, EL_CHAR('B') },
4719 { Xalpha_c, EL_CHAR('C') },
4720 { Xalpha_d, EL_CHAR('D') },
4721 { Xalpha_e, EL_CHAR('E') },
4722 { Xalpha_f, EL_CHAR('F') },
4723 { Xalpha_g, EL_CHAR('G') },
4724 { Xalpha_h, EL_CHAR('H') },
4725 { Xalpha_i, EL_CHAR('I') },
4726 { Xalpha_j, EL_CHAR('J') },
4727 { Xalpha_k, EL_CHAR('K') },
4728 { Xalpha_l, EL_CHAR('L') },
4729 { Xalpha_m, EL_CHAR('M') },
4730 { Xalpha_n, EL_CHAR('N') },
4731 { Xalpha_o, EL_CHAR('O') },
4732 { Xalpha_p, EL_CHAR('P') },
4733 { Xalpha_q, EL_CHAR('Q') },
4734 { Xalpha_r, EL_CHAR('R') },
4735 { Xalpha_s, EL_CHAR('S') },
4736 { Xalpha_t, EL_CHAR('T') },
4737 { Xalpha_u, EL_CHAR('U') },
4738 { Xalpha_v, EL_CHAR('V') },
4739 { Xalpha_w, EL_CHAR('W') },
4740 { Xalpha_x, EL_CHAR('X') },
4741 { Xalpha_y, EL_CHAR('Y') },
4742 { Xalpha_z, EL_CHAR('Z') },
4743 { Xalpha_arrow_e, EL_CHAR('>') },
4744 { Xalpha_arrow_w, EL_CHAR('<') },
4745 { Xalpha_copyr, EL_CHAR('©') },
4747 { Zplayer, EL_PLAYER_1 },
4748 { Zplayer, EL_PLAYER_2 },
4749 { Zplayer, EL_PLAYER_3 },
4750 { Zplayer, EL_PLAYER_4 },
4752 { ZBORDER, EL_EMC_LEVEL_BORDER },
4757 if (!mapping_initialized)
4761 /* return "Xalpha_quest" for all undefined elements in mapping array */
4762 for (i = 0; i < NUM_FILE_ELEMENTS; i++)
4763 mapping_RND_to_EM[i] = Xalpha_quest;
4765 for (i = 0; mapping_RND_to_EM_list[i].element_rnd != -1; i++)
4766 mapping_RND_to_EM[mapping_RND_to_EM_list[i].element_rnd] =
4767 mapping_RND_to_EM_list[i].element_em;
4769 mapping_initialized = TRUE;
4772 if (element_rnd >= 0 && element_rnd < NUM_FILE_ELEMENTS)
4773 return mapping_RND_to_EM[element_rnd];
4775 Error(ERR_WARN, "invalid RND level element %d", element_rnd);
4780 int map_element_EM_to_RND(int element_em)
4782 static unsigned short mapping_EM_to_RND[TILE_MAX];
4783 static boolean mapping_initialized = FALSE;
4790 mapping_EM_to_RND_list[] =
4792 { Xblank, EL_EMPTY },
4793 { Yacid_splash_eB, EL_EMPTY },
4794 { Yacid_splash_wB, EL_EMPTY },
4796 #ifdef EM_ENGINE_BAD_ROLL
4797 { Xstone_force_e, EL_ROCK },
4798 { Xstone_force_w, EL_ROCK },
4799 { Xnut_force_e, EL_NUT },
4800 { Xnut_force_w, EL_NUT },
4801 { Xspring_force_e, EL_SPRING },
4802 { Xspring_force_w, EL_SPRING },
4803 { Xemerald_force_e, EL_EMERALD },
4804 { Xemerald_force_w, EL_EMERALD },
4805 { Xdiamond_force_e, EL_DIAMOND },
4806 { Xdiamond_force_w, EL_DIAMOND },
4807 { Xbomb_force_e, EL_BOMB },
4808 { Xbomb_force_w, EL_BOMB },
4811 { Xstone, EL_ROCK },
4812 { Xstone_pause, EL_ROCK },
4813 { Xstone_fall, EL_ROCK },
4814 { Ystone_s, EL_ROCK },
4815 { Ystone_sB, EL_ROCK },
4816 { Ystone_e, EL_ROCK },
4817 { Ystone_eB, EL_ROCK },
4818 { Ystone_w, EL_ROCK },
4819 { Ystone_wB, EL_ROCK },
4821 { Xnut_pause, EL_NUT },
4822 { Xnut_fall, EL_NUT },
4824 { Ynut_sB, EL_NUT },
4826 { Ynut_eB, EL_NUT },
4828 { Ynut_wB, EL_NUT },
4829 { Xbug_n, EL_BUG_UP },
4830 { Xbug_e, EL_BUG_RIGHT },
4831 { Xbug_s, EL_BUG_DOWN },
4832 { Xbug_w, EL_BUG_LEFT },
4833 { Xbug_gon, EL_BUG_UP },
4834 { Xbug_goe, EL_BUG_RIGHT },
4835 { Xbug_gos, EL_BUG_DOWN },
4836 { Xbug_gow, EL_BUG_LEFT },
4837 { Ybug_n, EL_BUG_UP },
4838 { Ybug_nB, EL_BUG_UP },
4839 { Ybug_e, EL_BUG_RIGHT },
4840 { Ybug_eB, EL_BUG_RIGHT },
4841 { Ybug_s, EL_BUG_DOWN },
4842 { Ybug_sB, EL_BUG_DOWN },
4843 { Ybug_w, EL_BUG_LEFT },
4844 { Ybug_wB, EL_BUG_LEFT },
4845 { Ybug_w_n, EL_BUG_UP },
4846 { Ybug_n_e, EL_BUG_RIGHT },
4847 { Ybug_e_s, EL_BUG_DOWN },
4848 { Ybug_s_w, EL_BUG_LEFT },
4849 { Ybug_e_n, EL_BUG_UP },
4850 { Ybug_s_e, EL_BUG_RIGHT },
4851 { Ybug_w_s, EL_BUG_DOWN },
4852 { Ybug_n_w, EL_BUG_LEFT },
4853 { Ybug_stone, EL_ROCK },
4854 { Ybug_spring, EL_SPRING },
4855 { Xtank_n, EL_SPACESHIP_UP },
4856 { Xtank_e, EL_SPACESHIP_RIGHT },
4857 { Xtank_s, EL_SPACESHIP_DOWN },
4858 { Xtank_w, EL_SPACESHIP_LEFT },
4859 { Xtank_gon, EL_SPACESHIP_UP },
4860 { Xtank_goe, EL_SPACESHIP_RIGHT },
4861 { Xtank_gos, EL_SPACESHIP_DOWN },
4862 { Xtank_gow, EL_SPACESHIP_LEFT },
4863 { Ytank_n, EL_SPACESHIP_UP },
4864 { Ytank_nB, EL_SPACESHIP_UP },
4865 { Ytank_e, EL_SPACESHIP_RIGHT },
4866 { Ytank_eB, EL_SPACESHIP_RIGHT },
4867 { Ytank_s, EL_SPACESHIP_DOWN },
4868 { Ytank_sB, EL_SPACESHIP_DOWN },
4869 { Ytank_w, EL_SPACESHIP_LEFT },
4870 { Ytank_wB, EL_SPACESHIP_LEFT },
4871 { Ytank_w_n, EL_SPACESHIP_UP },
4872 { Ytank_n_e, EL_SPACESHIP_RIGHT },
4873 { Ytank_e_s, EL_SPACESHIP_DOWN },
4874 { Ytank_s_w, EL_SPACESHIP_LEFT },
4875 { Ytank_e_n, EL_SPACESHIP_UP },
4876 { Ytank_s_e, EL_SPACESHIP_RIGHT },
4877 { Ytank_w_s, EL_SPACESHIP_DOWN },
4878 { Ytank_n_w, EL_SPACESHIP_LEFT },
4879 { Ytank_stone, EL_ROCK },
4880 { Ytank_spring, EL_SPRING },
4881 { Xandroid, EL_EMC_ANDROID },
4882 { Xandroid_1_n, EL_EMC_ANDROID_UP },
4883 { Xandroid_2_n, EL_EMC_ANDROID_UP },
4884 { Xandroid_1_e, EL_EMC_ANDROID_RIGHT },
4885 { Xandroid_2_e, EL_EMC_ANDROID_RIGHT },
4886 { Xandroid_1_w, EL_EMC_ANDROID_LEFT },
4887 { Xandroid_2_w, EL_EMC_ANDROID_LEFT },
4888 { Xandroid_1_s, EL_EMC_ANDROID_DOWN },
4889 { Xandroid_2_s, EL_EMC_ANDROID_DOWN },
4890 { Yandroid_n, EL_EMC_ANDROID_UP },
4891 { Yandroid_nB, EL_EMC_ANDROID_UP },
4892 { Yandroid_ne, EL_EMC_ANDROID_RIGHT_UP },
4893 { Yandroid_neB, EL_EMC_ANDROID_RIGHT_UP },
4894 { Yandroid_e, EL_EMC_ANDROID_RIGHT },
4895 { Yandroid_eB, EL_EMC_ANDROID_RIGHT },
4896 { Yandroid_se, EL_EMC_ANDROID_RIGHT_DOWN },
4897 { Yandroid_seB, EL_EMC_ANDROID_RIGHT_DOWN },
4898 { Yandroid_s, EL_EMC_ANDROID_DOWN },
4899 { Yandroid_sB, EL_EMC_ANDROID_DOWN },
4900 { Yandroid_sw, EL_EMC_ANDROID_LEFT_DOWN },
4901 { Yandroid_swB, EL_EMC_ANDROID_LEFT_DOWN },
4902 { Yandroid_w, EL_EMC_ANDROID_LEFT },
4903 { Yandroid_wB, EL_EMC_ANDROID_LEFT },
4904 { Yandroid_nw, EL_EMC_ANDROID_LEFT_UP },
4905 { Yandroid_nwB, EL_EMC_ANDROID_LEFT_UP },
4906 { Xspring, EL_SPRING },
4907 { Xspring_pause, EL_SPRING },
4908 { Xspring_e, EL_SPRING },
4909 { Xspring_w, EL_SPRING },
4910 { Xspring_fall, EL_SPRING },
4911 { Yspring_s, EL_SPRING },
4912 { Yspring_sB, EL_SPRING },
4913 { Yspring_e, EL_SPRING },
4914 { Yspring_eB, EL_SPRING },
4915 { Yspring_w, EL_SPRING },
4916 { Yspring_wB, EL_SPRING },
4917 { Yspring_kill_e, EL_SPRING },
4918 { Yspring_kill_eB, EL_SPRING },
4919 { Yspring_kill_w, EL_SPRING },
4920 { Yspring_kill_wB, EL_SPRING },
4921 { Xeater_n, EL_YAMYAM },
4922 { Xeater_e, EL_YAMYAM },
4923 { Xeater_w, EL_YAMYAM },
4924 { Xeater_s, EL_YAMYAM },
4925 { Yeater_n, EL_YAMYAM },
4926 { Yeater_nB, EL_YAMYAM },
4927 { Yeater_e, EL_YAMYAM },
4928 { Yeater_eB, EL_YAMYAM },
4929 { Yeater_s, EL_YAMYAM },
4930 { Yeater_sB, EL_YAMYAM },
4931 { Yeater_w, EL_YAMYAM },
4932 { Yeater_wB, EL_YAMYAM },
4933 { Yeater_stone, EL_ROCK },
4934 { Yeater_spring, EL_SPRING },
4935 { Xalien, EL_ROBOT },
4936 { Xalien_pause, EL_ROBOT },
4937 { Yalien_n, EL_ROBOT },
4938 { Yalien_nB, EL_ROBOT },
4939 { Yalien_e, EL_ROBOT },
4940 { Yalien_eB, EL_ROBOT },
4941 { Yalien_s, EL_ROBOT },
4942 { Yalien_sB, EL_ROBOT },
4943 { Yalien_w, EL_ROBOT },
4944 { Yalien_wB, EL_ROBOT },
4945 { Yalien_stone, EL_ROCK },
4946 { Yalien_spring, EL_SPRING },
4947 { Xemerald, EL_EMERALD },
4948 { Xemerald_pause, EL_EMERALD },
4949 { Xemerald_fall, EL_EMERALD },
4950 { Xemerald_shine, EL_EMERALD },
4951 { Yemerald_s, EL_EMERALD },
4952 { Yemerald_sB, EL_EMERALD },
4953 { Yemerald_e, EL_EMERALD },
4954 { Yemerald_eB, EL_EMERALD },
4955 { Yemerald_w, EL_EMERALD },
4956 { Yemerald_wB, EL_EMERALD },
4957 { Yemerald_eat, EL_EMERALD },
4958 { Yemerald_stone, EL_ROCK },
4959 { Xdiamond, EL_DIAMOND },
4960 { Xdiamond_pause, EL_DIAMOND },
4961 { Xdiamond_fall, EL_DIAMOND },
4962 { Xdiamond_shine, EL_DIAMOND },
4963 { Ydiamond_s, EL_DIAMOND },
4964 { Ydiamond_sB, EL_DIAMOND },
4965 { Ydiamond_e, EL_DIAMOND },
4966 { Ydiamond_eB, EL_DIAMOND },
4967 { Ydiamond_w, EL_DIAMOND },
4968 { Ydiamond_wB, EL_DIAMOND },
4969 { Ydiamond_eat, EL_DIAMOND },
4970 { Ydiamond_stone, EL_ROCK },
4971 { Xdrip_fall, EL_AMOEBA_DROP },
4972 { Xdrip_stretch, EL_AMOEBA_DROP },
4973 { Xdrip_stretchB, EL_AMOEBA_DROP },
4974 { Xdrip_eat, EL_AMOEBA_DROP },
4975 { Ydrip_s1, EL_AMOEBA_DROP },
4976 { Ydrip_s1B, EL_AMOEBA_DROP },
4977 { Ydrip_s2, EL_AMOEBA_DROP },
4978 { Ydrip_s2B, EL_AMOEBA_DROP },
4980 { Xbomb_pause, EL_BOMB },
4981 { Xbomb_fall, EL_BOMB },
4982 { Ybomb_s, EL_BOMB },
4983 { Ybomb_sB, EL_BOMB },
4984 { Ybomb_e, EL_BOMB },
4985 { Ybomb_eB, EL_BOMB },
4986 { Ybomb_w, EL_BOMB },
4987 { Ybomb_wB, EL_BOMB },
4988 { Ybomb_eat, EL_BOMB },
4989 { Xballoon, EL_BALLOON },
4990 { Yballoon_n, EL_BALLOON },
4991 { Yballoon_nB, EL_BALLOON },
4992 { Yballoon_e, EL_BALLOON },
4993 { Yballoon_eB, EL_BALLOON },
4994 { Yballoon_s, EL_BALLOON },
4995 { Yballoon_sB, EL_BALLOON },
4996 { Yballoon_w, EL_BALLOON },
4997 { Yballoon_wB, EL_BALLOON },
4998 { Xgrass, EL_SAND },
4999 { Ygrass_nB, EL_SAND },
5000 { Ygrass_eB, EL_SAND },
5001 { Ygrass_sB, EL_SAND },
5002 { Ygrass_wB, EL_SAND },
5004 { Ydirt_nB, EL_SAND },
5005 { Ydirt_eB, EL_SAND },
5006 { Ydirt_sB, EL_SAND },
5007 { Ydirt_wB, EL_SAND },
5008 { Xacid_ne, EL_ACID_POOL_TOPRIGHT },
5009 { Xacid_se, EL_ACID_POOL_BOTTOMRIGHT },
5010 { Xacid_s, EL_ACID_POOL_BOTTOM },
5011 { Xacid_sw, EL_ACID_POOL_BOTTOMLEFT },
5012 { Xacid_nw, EL_ACID_POOL_TOPLEFT },
5013 { Xacid_1, EL_ACID },
5014 { Xacid_2, EL_ACID },
5015 { Xacid_3, EL_ACID },
5016 { Xacid_4, EL_ACID },
5017 { Xacid_5, EL_ACID },
5018 { Xacid_6, EL_ACID },
5019 { Xacid_7, EL_ACID },
5020 { Xacid_8, EL_ACID },
5021 { Xball_1, EL_EMC_MAGIC_BALL },
5022 { Xball_1B, EL_EMC_MAGIC_BALL },
5023 { Xball_2, EL_EMC_MAGIC_BALL },
5024 { Xball_2B, EL_EMC_MAGIC_BALL },
5025 { Yball_eat, EL_EMC_MAGIC_BALL },
5026 { Xgrow_ns, EL_EMC_GROW },
5027 { Ygrow_ns_eat, EL_EMC_GROW },
5028 { Xgrow_ew, EL_EMC_GROW },
5029 { Ygrow_ew_eat, EL_EMC_GROW },
5030 { Xwonderwall, EL_MAGIC_WALL },
5031 { XwonderwallB, EL_MAGIC_WALL },
5032 { Xamoeba_1, EL_AMOEBA_WET },
5033 { Xamoeba_2, EL_AMOEBA_WET },
5034 { Xamoeba_3, EL_AMOEBA_WET },
5035 { Xamoeba_4, EL_AMOEBA_WET },
5036 { Xamoeba_5, EL_AMOEBA_WET },
5037 { Xamoeba_6, EL_AMOEBA_WET },
5038 { Xamoeba_7, EL_AMOEBA_WET },
5039 { Xamoeba_8, EL_AMOEBA_WET },
5040 { Xdoor_1, EL_EM_GATE_1 },
5041 { Xdoor_2, EL_EM_GATE_2 },
5042 { Xdoor_3, EL_EM_GATE_3 },
5043 { Xdoor_4, EL_EM_GATE_4 },
5044 { Xdoor_5, EL_EMC_GATE_5 },
5045 { Xdoor_6, EL_EMC_GATE_6 },
5046 { Xdoor_7, EL_EMC_GATE_7 },
5047 { Xdoor_8, EL_EMC_GATE_8 },
5048 { Xkey_1, EL_EM_KEY_1 },
5049 { Xkey_2, EL_EM_KEY_2 },
5050 { Xkey_3, EL_EM_KEY_3 },
5051 { Xkey_4, EL_EM_KEY_4 },
5052 { Xkey_5, EL_EMC_KEY_5 },
5053 { Xkey_6, EL_EMC_KEY_6 },
5054 { Xkey_7, EL_EMC_KEY_7 },
5055 { Xkey_8, EL_EMC_KEY_8 },
5056 { Xwind_n, EL_BALLOON_SWITCH_UP },
5057 { Xwind_e, EL_BALLOON_SWITCH_RIGHT },
5058 { Xwind_s, EL_BALLOON_SWITCH_DOWN },
5059 { Xwind_w, EL_BALLOON_SWITCH_LEFT },
5060 { Xwind_nesw, EL_BALLOON_SWITCH_ANY },
5061 { Xwind_stop, EL_BALLOON_SWITCH_NONE },
5062 { Xexit, EL_EXIT_CLOSED },
5063 { Xexit_1, EL_EXIT_OPEN },
5064 { Xexit_2, EL_EXIT_OPEN },
5065 { Xexit_3, EL_EXIT_OPEN },
5066 { Xdynamite, EL_DYNAMITE },
5067 { Ydynamite_eat, EL_DYNAMITE },
5068 { Xdynamite_1, EL_DYNAMITE_ACTIVE },
5069 { Xdynamite_2, EL_DYNAMITE_ACTIVE },
5070 { Xdynamite_3, EL_DYNAMITE_ACTIVE },
5071 { Xdynamite_4, EL_DYNAMITE_ACTIVE },
5072 { Xbumper, EL_EMC_BUMPER },
5073 { XbumperB, EL_EMC_BUMPER },
5074 { Xwheel, EL_ROBOT_WHEEL },
5075 { XwheelB, EL_ROBOT_WHEEL },
5076 { Xswitch, EL_UNKNOWN },
5077 { XswitchB, EL_UNKNOWN },
5078 { Xsand, EL_QUICKSAND_EMPTY },
5079 { Xsand_stone, EL_QUICKSAND_FULL },
5080 { Xsand_stonein_1, EL_QUICKSAND_FULL },
5081 { Xsand_stonein_2, EL_QUICKSAND_FULL },
5082 { Xsand_stonein_3, EL_QUICKSAND_FULL },
5083 { Xsand_stonein_4, EL_QUICKSAND_FULL },
5084 { Xsand_stonesand_1, EL_QUICKSAND_FULL },
5085 { Xsand_stonesand_2, EL_QUICKSAND_FULL },
5086 { Xsand_stonesand_3, EL_QUICKSAND_FULL },
5087 { Xsand_stonesand_4, EL_QUICKSAND_FULL },
5088 { Xsand_stoneout_1, EL_QUICKSAND_FULL },
5089 { Xsand_stoneout_2, EL_QUICKSAND_FULL },
5090 { Xsand_sandstone_1, EL_QUICKSAND_FULL },
5091 { Xsand_sandstone_2, EL_QUICKSAND_FULL },
5092 { Xsand_sandstone_3, EL_QUICKSAND_FULL },
5093 { Xsand_sandstone_4, EL_QUICKSAND_FULL },
5094 { Xplant, EL_EMC_PLANT },
5095 { Yplant, EL_EMC_PLANT },
5096 { Xlenses, EL_EMC_LENSES },
5097 { Xmagnify, EL_EMC_MAGNIFIER },
5098 { Xdripper, EL_UNKNOWN },
5099 { XdripperB, EL_UNKNOWN },
5100 { Xfake_blank, EL_INVISIBLE_WALL },
5101 { Xfake_blankB, EL_INVISIBLE_WALL },
5102 { Xfake_grass, EL_INVISIBLE_SAND },
5103 { Xfake_grassB, EL_INVISIBLE_SAND },
5104 { Xfake_door_1, EL_EM_GATE_1_GRAY },
5105 { Xfake_door_2, EL_EM_GATE_2_GRAY },
5106 { Xfake_door_3, EL_EM_GATE_3_GRAY },
5107 { Xfake_door_4, EL_EM_GATE_4_GRAY },
5108 { Xfake_door_5, EL_EMC_GATE_5_GRAY },
5109 { Xfake_door_6, EL_EMC_GATE_6_GRAY },
5110 { Xfake_door_7, EL_EMC_GATE_7_GRAY },
5111 { Xfake_door_8, EL_EMC_GATE_8_GRAY },
5112 { Xsteel_1, EL_STEELWALL },
5113 { Xsteel_2, EL_UNKNOWN },
5114 { Xsteel_3, EL_EMC_STEELWALL_1 },
5115 { Xsteel_4, EL_UNKNOWN },
5116 { Xwall_1, EL_WALL },
5117 { Xwall_2, EL_UNKNOWN },
5118 { Xwall_3, EL_UNKNOWN },
5119 { Xwall_4, EL_UNKNOWN },
5120 { Xround_wall_1, EL_WALL_SLIPPERY },
5121 { Xround_wall_2, EL_UNKNOWN },
5122 { Xround_wall_3, EL_UNKNOWN },
5123 { Xround_wall_4, EL_UNKNOWN },
5124 { Xdecor_1, EL_UNKNOWN },
5125 { Xdecor_2, EL_EMC_WALL_6 },
5126 { Xdecor_3, EL_EMC_WALL_4 },
5127 { Xdecor_4, EL_EMC_WALL_5 },
5128 { Xdecor_5, EL_EMC_WALL_7 },
5129 { Xdecor_6, EL_EMC_WALL_8 },
5130 { Xdecor_7, EL_UNKNOWN },
5131 { Xdecor_8, EL_EMC_WALL_1 },
5132 { Xdecor_9, EL_EMC_WALL_2 },
5133 { Xdecor_10, EL_EMC_WALL_3 },
5134 { Xdecor_11, EL_UNKNOWN },
5135 { Xdecor_12, EL_UNKNOWN },
5136 { Xalpha_0, EL_CHAR('0') },
5137 { Xalpha_1, EL_CHAR('1') },
5138 { Xalpha_2, EL_CHAR('2') },
5139 { Xalpha_3, EL_CHAR('3') },
5140 { Xalpha_4, EL_CHAR('4') },
5141 { Xalpha_5, EL_CHAR('5') },
5142 { Xalpha_6, EL_CHAR('6') },
5143 { Xalpha_7, EL_CHAR('7') },
5144 { Xalpha_8, EL_CHAR('8') },
5145 { Xalpha_9, EL_CHAR('9') },
5146 { Xalpha_excla, EL_CHAR('!') },
5147 { Xalpha_quote, EL_CHAR('"') },
5148 { Xalpha_comma, EL_CHAR(',') },
5149 { Xalpha_minus, EL_CHAR('-') },
5150 { Xalpha_perio, EL_CHAR('.') },
5151 { Xalpha_colon, EL_CHAR(':') },
5152 { Xalpha_quest, EL_CHAR('?') },
5153 { Xalpha_a, EL_CHAR('A') },
5154 { Xalpha_b, EL_CHAR('B') },
5155 { Xalpha_c, EL_CHAR('C') },
5156 { Xalpha_d, EL_CHAR('D') },
5157 { Xalpha_e, EL_CHAR('E') },
5158 { Xalpha_f, EL_CHAR('F') },
5159 { Xalpha_g, EL_CHAR('G') },
5160 { Xalpha_h, EL_CHAR('H') },
5161 { Xalpha_i, EL_CHAR('I') },
5162 { Xalpha_j, EL_CHAR('J') },
5163 { Xalpha_k, EL_CHAR('K') },
5164 { Xalpha_l, EL_CHAR('L') },
5165 { Xalpha_m, EL_CHAR('M') },
5166 { Xalpha_n, EL_CHAR('N') },
5167 { Xalpha_o, EL_CHAR('O') },
5168 { Xalpha_p, EL_CHAR('P') },
5169 { Xalpha_q, EL_CHAR('Q') },
5170 { Xalpha_r, EL_CHAR('R') },
5171 { Xalpha_s, EL_CHAR('S') },
5172 { Xalpha_t, EL_CHAR('T') },
5173 { Xalpha_u, EL_CHAR('U') },
5174 { Xalpha_v, EL_CHAR('V') },
5175 { Xalpha_w, EL_CHAR('W') },
5176 { Xalpha_x, EL_CHAR('X') },
5177 { Xalpha_y, EL_CHAR('Y') },
5178 { Xalpha_z, EL_CHAR('Z') },
5179 { Xalpha_arrow_e, EL_CHAR('>') },
5180 { Xalpha_arrow_w, EL_CHAR('<') },
5181 { Xalpha_copyr, EL_CHAR('©') },
5183 { Zplayer, EL_PLAYER_1 },
5185 { ZBORDER, EL_EMC_LEVEL_BORDER },
5190 if (!mapping_initialized)
5194 /* return "EL_UNKNOWN" for all undefined elements in mapping array */
5195 for (i = 0; i < TILE_MAX; i++)
5196 mapping_EM_to_RND[i] = EL_UNKNOWN;
5198 for (i = 0; mapping_EM_to_RND_list[i].element_em != -1; i++)
5199 mapping_EM_to_RND[mapping_EM_to_RND_list[i].element_em] =
5200 mapping_EM_to_RND_list[i].element_rnd;
5202 mapping_initialized = TRUE;
5205 if (element_em >= 0 && element_em < TILE_MAX)
5206 return mapping_EM_to_RND[element_em];
5208 Error(ERR_WARN, "invalid EM level element %d", element_em);
5215 int get_next_element(int element)
5219 case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL;
5220 case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY;
5221 case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL;
5222 case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_ACTIVE;
5223 case EL_BD_MAGIC_WALL_FILLING: return EL_BD_MAGIC_WALL_FULL;
5224 case EL_BD_MAGIC_WALL_EMPTYING: return EL_BD_MAGIC_WALL_ACTIVE;
5225 case EL_AMOEBA_DROPPING: return EL_AMOEBA_WET;
5227 default: return element;
5231 int el_act_dir2img(int element, int action, int direction)
5233 element = GFX_ELEMENT(element);
5234 direction = MV_DIR_BIT(direction); /* default: MV_NO_MOVING => MV_DOWN */
5236 return element_info[element].direction_graphic[action][direction];
5239 static int el_act_dir2crm(int element, int action, int direction)
5241 element = GFX_ELEMENT(element);
5242 direction = MV_DIR_BIT(direction); /* default: MV_NO_MOVING => MV_DOWN */
5244 return element_info[element].direction_crumbled[action][direction];
5247 int el_act2img(int element, int action)
5249 element = GFX_ELEMENT(element);
5251 return element_info[element].graphic[action];
5254 int el_act2crm(int element, int action)
5256 element = GFX_ELEMENT(element);
5258 return element_info[element].crumbled[action];
5261 int el_dir2img(int element, int direction)
5263 element = GFX_ELEMENT(element);
5265 return el_act_dir2img(element, ACTION_DEFAULT, direction);
5268 int el2baseimg(int element)
5270 return element_info[element].graphic[ACTION_DEFAULT];
5273 int el2img(int element)
5275 element = GFX_ELEMENT(element);
5277 return element_info[element].graphic[ACTION_DEFAULT];
5280 int el2edimg(int element)
5282 element = GFX_ELEMENT(element);
5284 return element_info[element].special_graphic[GFX_SPECIAL_ARG_EDITOR];
5287 int el2preimg(int element)
5289 element = GFX_ELEMENT(element);
5291 return element_info[element].special_graphic[GFX_SPECIAL_ARG_PREVIEW];
5294 int getGameFrameDelay_EM(int native_em_game_frame_delay)
5296 return (GameFrameDelay == GAME_FRAME_DELAY ? native_em_game_frame_delay :
5300 unsigned int InitRND(long seed)
5302 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
5303 return InitEngineRND_EM(seed);
5305 return InitEngineRND(seed);
5308 void InitGraphicInfo_EM(void)
5310 int mapping_EM_to_RND_element[TILE_MAX];
5311 int mapping_EM_to_RND_action[TILE_MAX];
5312 int mapping_EM_to_RND_direction[TILE_MAX];
5313 boolean mapping_EM_to_RND_backside[TILE_MAX];
5316 /* return "EL_UNKNOWN" for all undefined elements in mapping array */
5317 for (i = 0; i < TILE_MAX; i++)
5319 mapping_EM_to_RND_element[i] = EL_UNKNOWN;
5320 mapping_EM_to_RND_backside[i] = FALSE;
5321 mapping_EM_to_RND_action[i] = ACTION_DEFAULT;
5322 mapping_EM_to_RND_direction[i] = MV_NO_MOVING;
5325 for (i = 0; mapping_EM_to_RND_list[i].element_em != -1; i++)
5327 int e = mapping_EM_to_RND_list[i].element_em;
5329 mapping_EM_to_RND_element[e] = mapping_EM_to_RND_list[i].element_rnd;
5330 mapping_EM_to_RND_backside[e] = mapping_EM_to_RND_list[i].is_backside;
5332 if (mapping_EM_to_RND_list[i].action != -1)
5333 mapping_EM_to_RND_action[e] = mapping_EM_to_RND_list[i].action;
5335 if (mapping_EM_to_RND_list[i].direction != -1)
5336 mapping_EM_to_RND_direction[e] = 1<< mapping_EM_to_RND_list[i].direction;
5339 for (i = 0; i < TILE_MAX; i++)
5341 int element = mapping_EM_to_RND_element[i];
5342 int action = mapping_EM_to_RND_action[i];
5343 int direction = mapping_EM_to_RND_direction[i];
5344 int backside = mapping_EM_to_RND_backside[i];
5345 boolean action_removing = (action == ACTION_DIGGING ||
5346 action == ACTION_SNAPPING ||
5347 action == ACTION_COLLECTING);
5348 boolean action_exploding = ((action == ACTION_EXPLODING ||
5349 action == ACTION_SMASHED_BY_ROCK ||
5350 action == ACTION_SMASHED_BY_SPRING) &&
5351 element != EL_DIAMOND);
5352 boolean action_active = (action == ACTION_ACTIVE);
5353 boolean action_other = (action == ACTION_OTHER);
5355 for (j = 0; j < 8; j++)
5357 int effective_element = (j < 7 ? element :
5358 i == Ynut_sB ? element :
5359 i == Xdrip_stretch ? element :
5360 i == Xdrip_stretchB ? element :
5361 i == Ydrip_s1 ? element :
5362 i == Ydrip_s1B ? element :
5363 i == Xball_1B ? element :
5364 i == Xball_2 ? element :
5365 i == Xball_2B ? element :
5366 i == Yball_eat ? element :
5367 i == Yspring_kill_e ? EL_SPRING :
5368 i == Yspring_kill_w ? EL_SPRING :
5369 i == Yemerald_stone ? EL_EMERALD :
5370 i == Ydiamond_stone ? EL_ROCK :
5371 backside ? EL_EMPTY :
5372 action_removing ? EL_EMPTY :
5374 int effective_action = (j < 7 ? action :
5375 i == Ynut_sB ? action :
5376 i == Xdrip_stretch ? action :
5377 i == Xdrip_stretchB ? action :
5378 i == Ydrip_s1 ? action :
5379 i == Ydrip_s1B ? action :
5380 i == Xball_1B ? action :
5381 i == Xball_2 ? action :
5382 i == Xball_2B ? action :
5383 i == Yball_eat ? action :
5384 i == Xsand_stonein_1 ? action :
5385 i == Xsand_stonein_2 ? action :
5386 i == Xsand_stonein_3 ? action :
5387 i == Xsand_stonein_4 ? action :
5388 i == Xsand_stoneout_1 ? action :
5389 i == Xsand_stoneout_2 ? action :
5390 i == Xboom_android ? ACTION_EXPLODING :
5391 action_exploding ? ACTION_EXPLODING :
5392 action_active ? action :
5393 action_other ? action :
5395 int graphic = (direction == MV_NO_MOVING ?
5396 el_act2img(effective_element, effective_action) :
5397 el_act_dir2img(effective_element, effective_action,
5399 struct GraphicInfo *g = &graphic_info[graphic];
5400 struct GraphicInfo_EM *g_em = &graphic_info_em[i][7 - j];
5403 int sync_frame = (i == Xdrip_stretch ? 7 :
5404 i == Xdrip_stretchB ? 7 :
5405 i == Ydrip_s2 ? j + 8 :
5406 i == Ydrip_s2B ? j + 8 :
5416 i == Xball_2B ? j + 8 :
5417 i == Yball_eat ? j + 1 :
5418 i == Xamoeba_1 ? 0 :
5419 i == Xamoeba_2 ? 1 :
5420 i == Xamoeba_3 ? 2 :
5421 i == Xamoeba_4 ? 3 :
5422 i == Xamoeba_5 ? 0 :
5423 i == Xamoeba_6 ? 1 :
5424 i == Xamoeba_7 ? 2 :
5425 i == Xamoeba_8 ? 3 :
5426 i == Xexit_2 ? j + 8 :
5427 i == Xexit_3 ? j + 16 :
5428 i == Xdynamite_1 ? 0 :
5429 i == Xdynamite_2 ? 2 :
5430 i == Xdynamite_3 ? 4 :
5431 i == Xdynamite_4 ? 6 :
5432 i == Xsand_stonein_1 ? j + 1 :
5433 i == Xsand_stonein_2 ? j + 9 :
5434 i == Xsand_stonein_3 ? j + 17 :
5435 i == Xsand_stonein_4 ? j + 25 :
5436 i == Xsand_stoneout_1 && j == 0 ? 1 :
5437 i == Xsand_stoneout_1 && j == 1 ? 1 :
5438 i == Xsand_stoneout_1 && j == 2 ? 2 :
5439 i == Xsand_stoneout_1 && j == 3 ? 4 :
5440 i == Xsand_stoneout_1 && j == 4 ? 4 :
5441 i == Xsand_stoneout_1 && j == 5 ? 6 :
5442 i == Xsand_stoneout_1 && j == 6 ? 8 :
5443 i == Xsand_stoneout_1 && j == 7 ? 8 :
5444 i == Xsand_stoneout_2 && j == 0 ? 10 :
5445 i == Xsand_stoneout_2 && j == 1 ? 12 :
5446 i == Xsand_stoneout_2 && j == 2 ? 14 :
5447 i == Xsand_stoneout_2 && j == 3 ? 16 :
5448 i == Xsand_stoneout_2 && j == 4 ? 18 :
5449 i == Xsand_stoneout_2 && j == 5 ? 22 :
5450 i == Xsand_stoneout_2 && j == 6 ? 26 :
5451 i == Xsand_stoneout_2 && j == 7 ? 30 :
5452 i == Xboom_bug && j == 2 ? 1 :
5453 i == Xboom_bug && j == 3 ? 2 :
5454 i == Xboom_bug && j == 4 ? 2 :
5455 i == Xboom_bug && j == 5 ? 1 :
5456 i == Xboom_bug && j == 6 ? 1 :
5457 i == Xboom_bug && j == 7 ? 0 :
5458 i == Xboom_bomb && j == 2 ? 1 :
5459 i == Xboom_bomb && j == 3 ? 2 :
5460 i == Xboom_bomb && j == 4 ? 2 :
5461 i == Xboom_bomb && j == 5 ? 1 :
5462 i == Xboom_bomb && j == 6 ? 1 :
5463 i == Xboom_bomb && j == 7 ? 0 :
5464 i == Xboom_android && j == 7 ? 3 :
5465 i == Xboom_1 && j == 2 ? 1 :
5466 i == Xboom_1 && j == 3 ? 2 :
5467 i == Xboom_1 && j == 4 ? 2 :
5468 i == Xboom_1 && j == 5 ? 3 :
5469 i == Xboom_1 && j == 6 ? 3 :
5470 i == Xboom_1 && j == 7 ? 4 :
5471 i == Xboom_2 && j == 0 ? 4 :
5472 i == Xboom_2 && j == 1 ? 4 :
5473 i == Xboom_2 && j == 2 ? 5 :
5474 i == Xboom_2 && j == 3 ? 5 :
5475 i == Xboom_2 && j == 4 ? 5 :
5476 i == Xboom_2 && j == 5 ? 6 :
5477 effective_action != action ? 0 :
5480 Bitmap *debug_bitmap = g_em->bitmap;
5481 int debug_src_x = g_em->src_x;
5482 int debug_src_y = g_em->src_y;
5485 int frame = getAnimationFrame(g->anim_frames,
5488 g->anim_start_frame,
5491 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y,
5492 g->double_movement && backside);
5495 g_em->bitmap = src_bitmap;
5496 g_em->src_x = src_x;
5497 g_em->src_y = src_y;
5498 g_em->src_offset_x = 0;
5499 g_em->src_offset_y = 0;
5500 g_em->dst_offset_x = 0;
5501 g_em->dst_offset_y = 0;
5502 g_em->width = TILEX;
5503 g_em->height = TILEY;
5507 if (!g->double_movement && (effective_action == ACTION_FALLING ||
5508 effective_action == ACTION_MOVING ||
5509 effective_action == ACTION_PUSHING))
5512 (effective_action == ACTION_FALLING ? MV_DOWN : direction);
5513 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? 1 : 0);
5514 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? 1 : 0);
5515 int cx = ABS(dx) * TILEX / 8;
5516 int cy = ABS(dy) * TILEY / 8;
5518 if (backside) /* tile where movement starts */
5520 if (dx < 0 || dy < 0)
5522 g_em->src_offset_x = cx * (j + 1);
5523 g_em->src_offset_y = cy * (j + 1);
5527 g_em->dst_offset_x = cx * (j + 1);
5528 g_em->dst_offset_y = cy * (j + 1);
5531 g_em->width = TILEX - cx * (j + 1);
5532 g_em->height = TILEY - cy * (j + 1);
5534 else /* tile where movement ends */
5536 if (dx < 0 || dy < 0)
5538 g_em->dst_offset_x = cx * (7 - j);
5539 g_em->dst_offset_y = cy * (7 - j);
5543 g_em->src_offset_x = cx * (7 - j);
5544 g_em->src_offset_y = cy * (7 - j);
5547 g_em->width = TILEX - cx * (7 - j);
5548 g_em->height = TILEY - cy * (7 - j);
5554 if (g_em->bitmap != debug_bitmap ||
5555 g_em->src_x != debug_src_x ||
5556 g_em->src_y != debug_src_y ||
5557 g_em->src_offset_x != 0 ||
5558 g_em->src_offset_y != 0 ||
5559 g_em->dst_offset_x != 0 ||
5560 g_em->dst_offset_y != 0 ||
5561 g_em->width != TILEX ||
5562 g_em->height != TILEY)
5564 static int last_i = -1;
5573 printf("::: EMC GFX ERROR for element %d -> %d ('%s')",
5574 i, element, element_info[element].token_name);
5576 if (element != effective_element)
5577 printf(" [%d ('%s')]",
5578 effective_element,element_info[effective_element].token_name);
5582 if (g_em->bitmap != debug_bitmap)
5583 printf(" %d(%d): different bitmap!\n",
5586 if (g_em->src_x != debug_src_x ||
5587 g_em->src_y != debug_src_y)
5588 printf(" frame %d (%c): %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
5589 j, (backside ? 'B' : 'F'),
5590 g_em->src_x, g_em->src_y,
5591 g_em->src_x / 32, g_em->src_y / 32,
5592 debug_src_x, debug_src_y,
5593 debug_src_x / 32, debug_src_y / 32);
5595 if (g_em->src_offset_x != 0 ||
5596 g_em->src_offset_y != 0 ||
5597 g_em->dst_offset_x != 0 ||
5598 g_em->dst_offset_y != 0)
5599 printf(" %d(%d): offsets %d,%d and %d,%d should be all 0\n",
5601 g_em->src_offset_x, g_em->src_offset_y,
5602 g_em->dst_offset_x, g_em->dst_offset_y);
5604 if (g_em->width != TILEX ||
5605 g_em->height != TILEY)
5606 printf(" %d(%d): size %d,%d should be %d,%d\n",
5608 g_em->width, g_em->height, TILEX, TILEY);