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 void getGraphicSource(int graphic, int frame, Bitmap **bitmap, int *x, int *y)
946 struct GraphicInfo *g = &graphic_info[graphic];
950 if (g->offset_y == 0) /* frames are ordered horizontally */
952 int max_width = g->anim_frames_per_line * g->width;
954 *x = (g->src_x + frame * g->offset_x) % max_width;
955 *y = g->src_y + (g->src_x + frame * g->offset_x) / max_width * g->height;
957 else if (g->offset_x == 0) /* frames are ordered vertically */
959 int max_height = g->anim_frames_per_line * g->height;
961 *x = g->src_x + (g->src_y + frame * g->offset_y) / max_height * g->width;
962 *y = (g->src_y + frame * g->offset_y) % max_height;
964 else /* frames are ordered diagonally */
966 *x = g->src_x + frame * g->offset_x;
967 *y = g->src_y + frame * g->offset_y;
971 void DrawGraphic(int x, int y, int graphic, int frame)
974 if (!IN_SCR_FIELD(x, y))
976 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
977 printf("DrawGraphic(): This should never happen!\n");
982 DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic, frame);
986 void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
992 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
993 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
996 void DrawGraphicThruMask(int x, int y, int graphic, int frame)
999 if (!IN_SCR_FIELD(x, y))
1001 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
1002 printf("DrawGraphicThruMask(): This should never happen!\n");
1007 DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY, graphic,
1009 MarkTileDirty(x, y);
1012 void DrawGraphicThruMaskExt(DrawBuffer *d, int dest_x, int dest_y, int graphic,
1020 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1021 drawing_gc = src_bitmap->stored_clip_gc;
1023 GC drawing_gc = src_bitmap->stored_clip_gc;
1024 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
1025 int src_x = graphic_info[graphic].src_x;
1026 int src_y = graphic_info[graphic].src_y;
1027 int offset_x = graphic_info[graphic].offset_x;
1028 int offset_y = graphic_info[graphic].offset_y;
1030 src_x += frame * offset_x;
1031 src_y += frame * offset_y;
1035 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1036 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dest_x, dest_y);
1039 void DrawMiniGraphic(int x, int y, int graphic)
1041 DrawMiniGraphicExt(drawto, SX + x * MINI_TILEX,SY + y * MINI_TILEY, graphic);
1042 MarkTileDirty(x / 2, y / 2);
1045 void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1047 struct GraphicInfo *g = &graphic_info[graphic];
1048 int mini_startx = 0;
1049 int mini_starty = g->bitmap->height * 2 / 3;
1051 *bitmap = g->bitmap;
1052 *x = mini_startx + g->src_x / 2;
1053 *y = mini_starty + g->src_y / 2;
1056 void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
1061 getMiniGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1062 BlitBitmap(src_bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
1065 void DrawGraphicShifted(int x, int y, int dx, int dy, int graphic, int frame,
1066 int cut_mode, int mask_mode)
1071 int width = TILEX, height = TILEY;
1077 DrawGraphic(x, y, graphic, frame);
1081 if (dx || dy) /* shifted graphic */
1083 if (x < BX1) /* object enters playfield from the left */
1090 else if (x > BX2) /* object enters playfield from the right */
1096 else if (x==BX1 && dx < 0) /* object leaves playfield to the left */
1102 else if (x==BX2 && dx > 0) /* object leaves playfield to the right */
1104 else if (dx) /* general horizontal movement */
1105 MarkTileDirty(x + SIGN(dx), y);
1107 if (y < BY1) /* object enters playfield from the top */
1109 if (cut_mode==CUT_BELOW) /* object completely above top border */
1117 else if (y > BY2) /* object enters playfield from the bottom */
1123 else if (y==BY1 && dy < 0) /* object leaves playfield to the top */
1129 else if (dy > 0 && cut_mode == CUT_ABOVE)
1131 if (y == BY2) /* object completely above bottom border */
1137 MarkTileDirty(x, y + 1);
1138 } /* object leaves playfield to the bottom */
1139 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1141 else if (dy) /* general vertical movement */
1142 MarkTileDirty(x, y + SIGN(dy));
1146 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1148 src_bitmap = graphic_info[graphic].bitmap;
1149 src_x = graphic_info[graphic].src_x;
1150 src_y = graphic_info[graphic].src_y;
1151 offset_x = graphic_info[graphic].offset_x;
1152 offset_y = graphic_info[graphic].offset_y;
1154 src_x += frame * offset_x;
1155 src_y += frame * offset_y;
1158 drawing_gc = src_bitmap->stored_clip_gc;
1163 dest_x = FX + x * TILEX + dx;
1164 dest_y = FY + y * TILEY + dy;
1167 if (!IN_SCR_FIELD(x,y))
1169 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1170 printf("DrawGraphicShifted(): This should never happen!\n");
1175 if (mask_mode == USE_MASKING)
1177 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1178 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
1182 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1185 MarkTileDirty(x, y);
1188 void DrawGraphicShiftedThruMask(int x, int y, int dx, int dy, int graphic,
1189 int frame, int cut_mode)
1191 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, USE_MASKING);
1194 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1195 int cut_mode, int mask_mode)
1197 int lx = LEVELX(x), ly = LEVELY(y);
1201 if (IN_LEV_FIELD(lx, ly))
1203 SetRandomAnimationValue(lx, ly);
1205 graphic = el_act_dir2img(element, GfxAction[lx][ly], GfxDir[lx][ly]);
1206 frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
1208 else /* border element */
1210 graphic = el2img(element);
1211 frame = getGraphicAnimationFrame(graphic, -1);
1214 if (element == EL_EXPANDABLE_WALL)
1216 boolean left_stopped = FALSE, right_stopped = FALSE;
1218 if (!IN_LEV_FIELD(lx - 1, ly) || IS_WALL(Feld[lx - 1][ly]))
1219 left_stopped = TRUE;
1220 if (!IN_LEV_FIELD(lx + 1, ly) || IS_WALL(Feld[lx + 1][ly]))
1221 right_stopped = TRUE;
1223 if (left_stopped && right_stopped)
1225 else if (left_stopped)
1227 graphic = IMG_EXPANDABLE_WALL_GROWING_RIGHT;
1228 frame = graphic_info[graphic].anim_frames - 1;
1230 else if (right_stopped)
1232 graphic = IMG_EXPANDABLE_WALL_GROWING_LEFT;
1233 frame = graphic_info[graphic].anim_frames - 1;
1238 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
1239 else if (mask_mode == USE_MASKING)
1240 DrawGraphicThruMask(x, y, graphic, frame);
1242 DrawGraphic(x, y, graphic, frame);
1245 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1246 int cut_mode, int mask_mode)
1248 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1249 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1250 cut_mode, mask_mode);
1253 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1256 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1259 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1262 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1265 void DrawLevelElementThruMask(int x, int y, int element)
1267 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1270 void DrawLevelFieldThruMask(int x, int y)
1272 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1275 #define TILE_GFX_ELEMENT(x, y) \
1276 (GfxElement[x][y] != EL_UNDEFINED && Feld[x][y] != EL_EXPLOSION ? \
1277 GfxElement[x][y] : Feld[x][y])
1279 static void DrawLevelFieldCrumbledSandExt(int x, int y, int graphic, int frame)
1283 int sx = SCREENX(x), sy = SCREENY(y);
1285 int width, height, cx, cy, i;
1287 int crumbled_border_size = graphic_info[graphic].border_size;
1289 int snip = TILEX / 8; /* number of border pixels from "crumbled graphic" */
1291 static int xy[4][2] =
1300 if (x == 0 && y == 7)
1301 printf("::: %d, %d [%d]\n", GfxElement[x][y], Feld[x][y],
1302 crumbled_border_size);
1305 if (!IN_LEV_FIELD(x, y))
1308 element = TILE_GFX_ELEMENT(x, y);
1310 /* crumble field itself */
1311 if (GFX_CRUMBLED(element) && !IS_MOVING(x, y))
1313 if (!IN_SCR_FIELD(sx, sy))
1316 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1318 for (i = 0; i < 4; i++)
1320 int xx = x + xy[i][0];
1321 int yy = y + xy[i][1];
1324 element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
1327 element = (IN_LEV_FIELD(xx, yy) ? Feld[xx][yy] : BorderElement);
1330 /* check if neighbour field is of same type */
1331 if (GFX_CRUMBLED(element) && !IS_MOVING(xx, yy))
1335 if (Feld[x][y] == EL_CUSTOM_START + 123)
1336 printf("::: crumble [%d] THE CHAOS ENGINE (%d, %d): %d, %d\n",
1337 i, Feld[x][y], element,
1338 GFX_CRUMBLED(element), IS_MOVING(x, y));
1341 if (i == 1 || i == 2)
1343 width = crumbled_border_size;
1345 cx = (i == 2 ? TILEX - crumbled_border_size : 0);
1351 height = crumbled_border_size;
1353 cy = (i == 3 ? TILEY - crumbled_border_size : 0);
1356 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1357 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
1360 MarkTileDirty(sx, sy);
1362 else /* crumble neighbour fields */
1365 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1368 for (i = 0; i < 4; i++)
1370 int xx = x + xy[i][0];
1371 int yy = y + xy[i][1];
1372 int sxx = sx + xy[i][0];
1373 int syy = sy + xy[i][1];
1376 if (!IN_LEV_FIELD(xx, yy) ||
1377 !IN_SCR_FIELD(sxx, syy) ||
1381 element = TILE_GFX_ELEMENT(xx, yy);
1383 if (!GFX_CRUMBLED(element))
1386 if (!IN_LEV_FIELD(xx, yy) ||
1387 !IN_SCR_FIELD(sxx, syy) ||
1388 !GFX_CRUMBLED(Feld[xx][yy]) ||
1394 graphic = el_act2crm(Feld[xx][yy], ACTION_DEFAULT);
1395 crumbled_border_size = graphic_info[graphic].border_size;
1397 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1400 if (i == 1 || i == 2)
1402 width = crumbled_border_size;
1404 cx = (i == 1 ? TILEX - crumbled_border_size : 0);
1410 height = crumbled_border_size;
1412 cy = (i == 0 ? TILEY - crumbled_border_size : 0);
1415 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1416 width, height, FX + sxx * TILEX + cx, FY + syy * TILEY + cy);
1418 MarkTileDirty(sxx, syy);
1423 void DrawLevelFieldCrumbledSand(int x, int y)
1428 if (!IN_LEV_FIELD(x, y))
1431 graphic = el_act2crm(Feld[x][y], ACTION_DEFAULT);
1433 DrawLevelFieldCrumbledSandExt(x, y, graphic, 0);
1435 DrawLevelFieldCrumbledSandExt(x, y, IMG_SAND_CRUMBLED, 0);
1439 void DrawLevelFieldCrumbledSandDigging(int x, int y, int direction,
1443 int graphic1 = el_act_dir2img(GfxElement[x][y], ACTION_DIGGING, direction);
1444 int graphic2 = el_act_dir2crm(GfxElement[x][y], ACTION_DIGGING, direction);
1446 int graphic1 = el_act_dir2img(EL_SAND, ACTION_DIGGING, direction);
1447 int graphic2 = el_act_dir2img(EL_SAND_CRUMBLED, ACTION_DIGGING, direction);
1449 int frame1 = getGraphicAnimationFrame(graphic1, step_frame);
1450 int frame2 = getGraphicAnimationFrame(graphic2, step_frame);
1451 int sx = SCREENX(x), sy = SCREENY(y);
1453 DrawGraphic(sx, sy, graphic1, frame1);
1454 DrawLevelFieldCrumbledSandExt(x, y, graphic2, frame2);
1457 void DrawLevelFieldCrumbledSandNeighbours(int x, int y)
1459 int sx = SCREENX(x), sy = SCREENY(y);
1460 static int xy[4][2] =
1469 for (i = 0; i < 4; i++)
1471 int xx = x + xy[i][0];
1472 int yy = y + xy[i][1];
1473 int sxx = sx + xy[i][0];
1474 int syy = sy + xy[i][1];
1476 if (!IN_LEV_FIELD(xx, yy) ||
1477 !IN_SCR_FIELD(sxx, syy) ||
1478 !GFX_CRUMBLED(Feld[xx][yy]) ||
1482 DrawLevelField(xx, yy);
1486 static int getBorderElement(int x, int y)
1490 { EL_STEELWALL_TOPLEFT, EL_INVISIBLE_STEELWALL_TOPLEFT },
1491 { EL_STEELWALL_TOPRIGHT, EL_INVISIBLE_STEELWALL_TOPRIGHT },
1492 { EL_STEELWALL_BOTTOMLEFT, EL_INVISIBLE_STEELWALL_BOTTOMLEFT },
1493 { EL_STEELWALL_BOTTOMRIGHT, EL_INVISIBLE_STEELWALL_BOTTOMRIGHT },
1494 { EL_STEELWALL_VERTICAL, EL_INVISIBLE_STEELWALL_VERTICAL },
1495 { EL_STEELWALL_HORIZONTAL, EL_INVISIBLE_STEELWALL_HORIZONTAL },
1496 { EL_STEELWALL, EL_INVISIBLE_STEELWALL }
1498 int steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
1499 int steel_position = (x == -1 && y == -1 ? 0 :
1500 x == lev_fieldx && y == -1 ? 1 :
1501 x == -1 && y == lev_fieldy ? 2 :
1502 x == lev_fieldx && y == lev_fieldy ? 3 :
1503 x == -1 || x == lev_fieldx ? 4 :
1504 y == -1 || y == lev_fieldy ? 5 : 6);
1506 return border[steel_position][steel_type];
1509 void DrawScreenElement(int x, int y, int element)
1511 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1512 DrawLevelFieldCrumbledSand(LEVELX(x), LEVELY(y));
1515 void DrawLevelElement(int x, int y, int element)
1517 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1518 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1521 void DrawScreenField(int x, int y)
1523 int lx = LEVELX(x), ly = LEVELY(y);
1524 int element, content;
1526 if (!IN_LEV_FIELD(lx, ly))
1528 if (lx < -1 || lx > lev_fieldx || ly < -1 || ly > lev_fieldy)
1531 element = getBorderElement(lx, ly);
1533 DrawScreenElement(x, y, element);
1537 element = Feld[lx][ly];
1538 content = Store[lx][ly];
1540 if (IS_MOVING(lx, ly))
1542 int horiz_move = (MovDir[lx][ly] == MV_LEFT || MovDir[lx][ly] == MV_RIGHT);
1543 boolean cut_mode = NO_CUTTING;
1545 if (element == EL_QUICKSAND_EMPTYING ||
1546 element == EL_MAGIC_WALL_EMPTYING ||
1547 element == EL_BD_MAGIC_WALL_EMPTYING ||
1548 element == EL_AMOEBA_DROPPING)
1549 cut_mode = CUT_ABOVE;
1550 else if (element == EL_QUICKSAND_FILLING ||
1551 element == EL_MAGIC_WALL_FILLING ||
1552 element == EL_BD_MAGIC_WALL_FILLING)
1553 cut_mode = CUT_BELOW;
1555 if (cut_mode == CUT_ABOVE)
1556 DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1558 DrawScreenElement(x, y, EL_EMPTY);
1561 DrawScreenElementShifted(x, y, MovPos[lx][ly], 0, element, NO_CUTTING);
1562 else if (cut_mode == NO_CUTTING)
1563 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], element, cut_mode);
1565 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], content, cut_mode);
1567 if (content == EL_ACID)
1569 int dir = MovDir[lx][ly];
1570 int newlx = lx + (dir == MV_LEFT ? -1 : dir == MV_RIGHT ? +1 : 0);
1571 int newly = ly + (dir == MV_UP ? -1 : dir == MV_DOWN ? +1 : 0);
1573 DrawLevelElementThruMask(newlx, newly, EL_ACID);
1576 else if (IS_BLOCKED(lx, ly))
1581 boolean cut_mode = NO_CUTTING;
1582 int element_old, content_old;
1584 Blocked2Moving(lx, ly, &oldx, &oldy);
1587 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1588 MovDir[oldx][oldy] == MV_RIGHT);
1590 element_old = Feld[oldx][oldy];
1591 content_old = Store[oldx][oldy];
1593 if (element_old == EL_QUICKSAND_EMPTYING ||
1594 element_old == EL_MAGIC_WALL_EMPTYING ||
1595 element_old == EL_BD_MAGIC_WALL_EMPTYING ||
1596 element_old == EL_AMOEBA_DROPPING)
1597 cut_mode = CUT_ABOVE;
1599 DrawScreenElement(x, y, EL_EMPTY);
1602 DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
1604 else if (cut_mode == NO_CUTTING)
1605 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
1608 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
1611 else if (IS_DRAWABLE(element))
1612 DrawScreenElement(x, y, element);
1614 DrawScreenElement(x, y, EL_EMPTY);
1617 void DrawLevelField(int x, int y)
1619 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1620 DrawScreenField(SCREENX(x), SCREENY(y));
1621 else if (IS_MOVING(x, y))
1625 Moving2Blocked(x, y, &newx, &newy);
1626 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1627 DrawScreenField(SCREENX(newx), SCREENY(newy));
1629 else if (IS_BLOCKED(x, y))
1633 Blocked2Moving(x, y, &oldx, &oldy);
1634 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1635 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1639 void DrawMiniElement(int x, int y, int element)
1643 graphic = el2edimg(element);
1644 DrawMiniGraphic(x, y, graphic);
1647 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1649 int x = sx + scroll_x, y = sy + scroll_y;
1651 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1652 DrawMiniElement(sx, sy, EL_EMPTY);
1653 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1654 DrawMiniElement(sx, sy, Feld[x][y]);
1656 DrawMiniGraphic(sx, sy, el2edimg(getBorderElement(x, y)));
1659 void DrawEnvelopeBackground(int envelope_nr, int startx, int starty,
1660 int x, int y, int xsize, int ysize, int font_nr)
1662 int font_width = getFontWidth(font_nr);
1663 int font_height = getFontHeight(font_nr);
1664 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1667 int dst_x = SX + startx + x * font_width;
1668 int dst_y = SY + starty + y * font_height;
1669 int width = graphic_info[graphic].width;
1670 int height = graphic_info[graphic].height;
1671 int inner_width = MAX(width - 2 * font_width, font_width);
1672 int inner_height = MAX(height - 2 * font_height, font_height);
1673 int inner_sx = (width >= 3 * font_width ? font_width : 0);
1674 int inner_sy = (height >= 3 * font_height ? font_height : 0);
1675 boolean draw_masked = graphic_info[graphic].draw_masked;
1677 getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
1679 if (src_bitmap == NULL || width < font_width || height < font_height)
1681 ClearRectangle(drawto, dst_x, dst_y, font_width, font_height);
1685 src_x += (x == 0 ? 0 : x == xsize - 1 ? width - font_width :
1686 inner_sx + (x - 1) * font_width % inner_width);
1687 src_y += (y == 0 ? 0 : y == ysize - 1 ? height - font_height :
1688 inner_sy + (y - 1) * font_height % inner_height);
1692 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1693 dst_x - src_x, dst_y - src_y);
1694 BlitBitmapMasked(src_bitmap, drawto, src_x, src_y, font_width, font_height,
1698 BlitBitmap(src_bitmap, drawto, src_x, src_y, font_width, font_height,
1702 void AnimateEnvelope(int envelope_nr, int anim_mode, int action)
1704 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1705 boolean draw_masked = graphic_info[graphic].draw_masked;
1706 int mask_mode = (draw_masked ? BLIT_MASKED : BLIT_ON_BACKGROUND);
1707 boolean ffwd_delay = (tape.playing && tape.fast_forward);
1708 boolean no_delay = (tape.warp_forward);
1709 unsigned long anim_delay = 0;
1710 int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
1711 int anim_delay_value = (no_delay ? 0 : frame_delay_value);
1712 int font_nr = FONT_ENVELOPE_1 + envelope_nr;
1713 int font_width = getFontWidth(font_nr);
1714 int font_height = getFontHeight(font_nr);
1715 int max_xsize = level.envelope_xsize[envelope_nr];
1716 int max_ysize = level.envelope_ysize[envelope_nr];
1717 int xstart = (anim_mode & ANIM_VERTICAL ? max_xsize : 0);
1718 int ystart = (anim_mode & ANIM_HORIZONTAL ? max_ysize : 0);
1719 int xend = max_xsize;
1720 int yend = (anim_mode != ANIM_DEFAULT ? max_ysize : 0);
1721 int xstep = (xstart < xend ? 1 : 0);
1722 int ystep = (ystart < yend || xstep == 0 ? 1 : 0);
1725 for (x = xstart, y = ystart; x <= xend && y <= yend; x += xstep, y += ystep)
1727 int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2;
1728 int ysize = (action == ACTION_CLOSING ? yend - (y - ystart) : y) + 2;
1729 int sx = (SXSIZE - xsize * font_width) / 2;
1730 int sy = (SYSIZE - ysize * font_height) / 2;
1733 SetDrawtoField(DRAW_BUFFERED);
1735 BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
1737 SetDrawtoField(DRAW_BACKBUFFER);
1739 for (yy = 0; yy < ysize; yy++) for (xx = 0; xx < xsize; xx++)
1740 DrawEnvelopeBackground(envelope_nr, sx,sy, xx,yy, xsize, ysize, font_nr);
1742 DrawTextToTextArea(SX + sx + font_width, SY + sy + font_height,
1743 level.envelope_text[envelope_nr], font_nr, max_xsize,
1744 xsize - 2, ysize - 2, mask_mode);
1746 redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
1749 WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
1753 void ShowEnvelope(int envelope_nr)
1755 int element = EL_ENVELOPE_1 + envelope_nr;
1756 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1757 int sound_opening = element_info[element].sound[ACTION_OPENING];
1758 int sound_closing = element_info[element].sound[ACTION_CLOSING];
1759 boolean ffwd_delay = (tape.playing && tape.fast_forward);
1760 boolean no_delay = (tape.warp_forward);
1761 int normal_delay_value = ONE_SECOND_DELAY / (ffwd_delay ? 2 : 1);
1762 int wait_delay_value = (no_delay ? 0 : normal_delay_value);
1763 int anim_mode = graphic_info[graphic].anim_mode;
1764 int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL:
1765 anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode);
1767 game.envelope_active = TRUE; /* needed for RedrawPlayfield() events */
1769 PlaySoundStereo(sound_opening, SOUND_MIDDLE);
1771 if (anim_mode == ANIM_DEFAULT)
1772 AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_OPENING);
1774 AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_OPENING);
1777 Delay(wait_delay_value);
1779 WaitForEventToContinue();
1781 PlaySoundStereo(sound_closing, SOUND_MIDDLE);
1783 if (anim_mode != ANIM_NONE)
1784 AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_CLOSING);
1786 if (anim_mode == ANIM_DEFAULT)
1787 AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_CLOSING);
1789 game.envelope_active = FALSE;
1791 SetDrawtoField(DRAW_BUFFERED);
1793 redraw_mask |= REDRAW_FIELD;
1797 void getMicroGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1799 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
1800 int mini_startx = src_bitmap->width * 3 / 4;
1801 int mini_starty = src_bitmap->height * 2 / 3;
1802 int src_x = mini_startx + graphic_info[graphic].src_x / 8;
1803 int src_y = mini_starty + graphic_info[graphic].src_y / 8;
1805 *bitmap = src_bitmap;
1810 void DrawMicroElement(int xpos, int ypos, int element)
1814 int graphic = el2preimg(element);
1816 getMicroGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1817 BlitBitmap(src_bitmap, drawto, src_x, src_y, MICRO_TILEX, MICRO_TILEY,
1825 SetDrawBackgroundMask(REDRAW_NONE);
1828 for (x = BX1; x <= BX2; x++)
1829 for (y = BY1; y <= BY2; y++)
1830 DrawScreenField(x, y);
1832 redraw_mask |= REDRAW_FIELD;
1835 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1839 for (x = 0; x < size_x; x++)
1840 for (y = 0; y < size_y; y++)
1841 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1843 redraw_mask |= REDRAW_FIELD;
1846 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1850 DrawBackground(xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
1852 if (lev_fieldx < STD_LEV_FIELDX)
1853 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1854 if (lev_fieldy < STD_LEV_FIELDY)
1855 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1857 xpos += MICRO_TILEX;
1858 ypos += MICRO_TILEY;
1860 for (x = -1; x <= STD_LEV_FIELDX; x++)
1862 for (y = -1; y <= STD_LEV_FIELDY; y++)
1864 int lx = from_x + x, ly = from_y + y;
1866 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1867 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1868 level.field[lx][ly]);
1869 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1
1870 && BorderElement != EL_EMPTY)
1871 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1872 getBorderElement(lx, ly));
1876 redraw_mask |= REDRAW_MICROLEVEL;
1879 #define MICROLABEL_EMPTY 0
1880 #define MICROLABEL_LEVEL_NAME 1
1881 #define MICROLABEL_CREATED_BY 2
1882 #define MICROLABEL_LEVEL_AUTHOR 3
1883 #define MICROLABEL_IMPORTED_FROM 4
1884 #define MICROLABEL_LEVEL_IMPORT_INFO 5
1886 static void DrawMicroLevelLabelExt(int mode)
1888 char label_text[MAX_OUTPUT_LINESIZE + 1];
1889 int max_len_label_text;
1890 int font_nr = FONT_TEXT_2;
1892 if (mode == MICROLABEL_CREATED_BY || mode == MICROLABEL_IMPORTED_FROM)
1893 font_nr = FONT_TEXT_3;
1895 max_len_label_text = SXSIZE / getFontWidth(font_nr);
1897 DrawBackground(SX, MICROLABEL_YPOS, SXSIZE, getFontHeight(font_nr));
1899 strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
1900 mode == MICROLABEL_CREATED_BY ? "created by" :
1901 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
1902 mode == MICROLABEL_IMPORTED_FROM ? "imported from" :
1903 mode == MICROLABEL_LEVEL_IMPORT_INFO ?
1904 leveldir_current->imported_from : ""),
1905 max_len_label_text);
1906 label_text[max_len_label_text] = '\0';
1908 if (strlen(label_text) > 0)
1910 int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
1911 int lypos = MICROLABEL_YPOS;
1913 DrawText(lxpos, lypos, label_text, font_nr);
1916 redraw_mask |= REDRAW_MICROLEVEL;
1919 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1921 static unsigned long scroll_delay = 0;
1922 static unsigned long label_delay = 0;
1923 static int from_x, from_y, scroll_direction;
1924 static int label_state, label_counter;
1925 int last_game_status = game_status; /* save current game status */
1927 /* force PREVIEW font on preview level */
1928 game_status = GAME_MODE_PSEUDO_PREVIEW;
1932 from_x = from_y = 0;
1933 scroll_direction = MV_RIGHT;
1937 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1938 DrawMicroLevelLabelExt(label_state);
1940 /* initialize delay counters */
1941 DelayReached(&scroll_delay, 0);
1942 DelayReached(&label_delay, 0);
1944 if (leveldir_current->name)
1946 int text_width = getTextWidth(leveldir_current->name, FONT_TEXT_1);
1947 int lxpos = SX + (SXSIZE - text_width) / 2;
1948 int lypos = SY + 352;
1950 DrawText(lxpos, lypos, leveldir_current->name, FONT_TEXT_1);
1953 game_status = last_game_status; /* restore current game status */
1958 /* scroll micro level, if needed */
1959 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1960 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1962 switch (scroll_direction)
1968 scroll_direction = MV_UP;
1972 if (from_x < lev_fieldx - STD_LEV_FIELDX)
1975 scroll_direction = MV_DOWN;
1982 scroll_direction = MV_RIGHT;
1986 if (from_y < lev_fieldy - STD_LEV_FIELDY)
1989 scroll_direction = MV_LEFT;
1996 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1999 /* redraw micro level label, if needed */
2000 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
2001 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
2002 strcmp(level.author, leveldir_current->name) != 0 &&
2003 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
2005 int max_label_counter = 23;
2007 if (leveldir_current->imported_from != NULL)
2008 max_label_counter += 14;
2010 label_counter = (label_counter + 1) % max_label_counter;
2011 label_state = (label_counter >= 0 && label_counter <= 7 ?
2012 MICROLABEL_LEVEL_NAME :
2013 label_counter >= 9 && label_counter <= 12 ?
2014 MICROLABEL_CREATED_BY :
2015 label_counter >= 14 && label_counter <= 21 ?
2016 MICROLABEL_LEVEL_AUTHOR :
2017 label_counter >= 23 && label_counter <= 26 ?
2018 MICROLABEL_IMPORTED_FROM :
2019 label_counter >= 28 && label_counter <= 35 ?
2020 MICROLABEL_LEVEL_IMPORT_INFO : MICROLABEL_EMPTY);
2021 DrawMicroLevelLabelExt(label_state);
2024 game_status = last_game_status; /* restore current game status */
2027 void WaitForEventToContinue()
2029 boolean still_wait = TRUE;
2031 /* simulate releasing mouse button over last gadget, if still pressed */
2033 HandleGadgets(-1, -1, 0);
2035 button_status = MB_RELEASED;
2047 case EVENT_BUTTONPRESS:
2048 case EVENT_KEYPRESS:
2052 case EVENT_KEYRELEASE:
2053 ClearPlayerAction();
2057 HandleOtherEvents(&event);
2061 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2068 /* don't eat all CPU time */
2073 #define MAX_REQUEST_LINES 13
2074 #define MAX_REQUEST_LINE_FONT1_LEN 7
2075 #define MAX_REQUEST_LINE_FONT2_LEN 10
2077 boolean Request(char *text, unsigned int req_state)
2079 int mx, my, ty, result = -1;
2080 unsigned int old_door_state;
2081 int last_game_status = game_status; /* save current game status */
2082 int max_request_line_len = MAX_REQUEST_LINE_FONT1_LEN;
2083 int font_nr = FONT_TEXT_2;
2084 int max_word_len = 0;
2087 for (text_ptr = text; *text_ptr; text_ptr++)
2089 max_word_len = (*text_ptr != ' ' ? max_word_len + 1 : 0);
2091 if (max_word_len > MAX_REQUEST_LINE_FONT1_LEN)
2093 max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
2094 font_nr = FONT_LEVEL_NUMBER;
2101 /* disable deactivated drawing when quick-loading level tape recording */
2102 if (tape.playing && tape.deactivate_display)
2103 TapeDeactivateDisplayOff(TRUE);
2107 SetMouseCursor(CURSOR_DEFAULT);
2110 #if defined(NETWORK_AVALIABLE)
2111 /* pause network game while waiting for request to answer */
2112 if (options.network &&
2113 game_status == GAME_MODE_PLAYING &&
2114 req_state & REQUEST_WAIT_FOR)
2115 SendToServer_PausePlaying();
2118 old_door_state = GetDoorState();
2120 /* simulate releasing mouse button over last gadget, if still pressed */
2122 HandleGadgets(-1, -1, 0);
2126 CloseDoor(DOOR_CLOSE_1);
2128 /* save old door content */
2129 BlitBitmap(bitmap_db_door, bitmap_db_door,
2130 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
2131 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
2133 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
2135 /* clear door drawing field */
2136 DrawBackground(DX, DY, DXSIZE, DYSIZE);
2138 /* force DOOR font on preview level */
2139 game_status = GAME_MODE_PSEUDO_DOOR;
2141 /* write text for request */
2142 for (ty = 0; ty < MAX_REQUEST_LINES; ty++)
2144 char text_line[max_request_line_len + 1];
2150 for (tl = 0, tx = 0; tx < max_request_line_len; tl++, tx++)
2153 if (!tc || tc == ' ')
2164 strncpy(text_line, text, tl);
2167 DrawText(DX + (DXSIZE - tl * getFontWidth(font_nr)) / 2,
2168 DY + 8 + ty * (getFontHeight(font_nr) + 2),
2169 text_line, font_nr);
2171 text += tl + (tc == ' ' ? 1 : 0);
2174 game_status = last_game_status; /* restore current game status */
2176 if (req_state & REQ_ASK)
2178 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
2179 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
2181 else if (req_state & REQ_CONFIRM)
2183 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
2185 else if (req_state & REQ_PLAYER)
2187 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
2188 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
2189 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
2190 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
2193 /* copy request gadgets to door backbuffer */
2194 BlitBitmap(drawto, bitmap_db_door,
2195 DX, DY, DXSIZE, DYSIZE,
2196 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2198 OpenDoor(DOOR_OPEN_1);
2204 if (!(req_state & REQUEST_WAIT_FOR))
2206 SetDrawBackgroundMask(REDRAW_FIELD);
2211 if (game_status != GAME_MODE_MAIN)
2214 button_status = MB_RELEASED;
2216 request_gadget_id = -1;
2218 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
2221 SetMouseCursor(CURSOR_DEFAULT);
2234 case EVENT_BUTTONPRESS:
2235 case EVENT_BUTTONRELEASE:
2236 case EVENT_MOTIONNOTIFY:
2238 if (event.type == EVENT_MOTIONNOTIFY)
2240 if (!PointerInWindow(window))
2241 continue; /* window and pointer are on different screens */
2246 motion_status = TRUE;
2247 mx = ((MotionEvent *) &event)->x;
2248 my = ((MotionEvent *) &event)->y;
2252 motion_status = FALSE;
2253 mx = ((ButtonEvent *) &event)->x;
2254 my = ((ButtonEvent *) &event)->y;
2255 if (event.type == EVENT_BUTTONPRESS)
2256 button_status = ((ButtonEvent *) &event)->button;
2258 button_status = MB_RELEASED;
2261 /* this sets 'request_gadget_id' */
2262 HandleGadgets(mx, my, button_status);
2264 switch(request_gadget_id)
2266 case TOOL_CTRL_ID_YES:
2269 case TOOL_CTRL_ID_NO:
2272 case TOOL_CTRL_ID_CONFIRM:
2273 result = TRUE | FALSE;
2276 case TOOL_CTRL_ID_PLAYER_1:
2279 case TOOL_CTRL_ID_PLAYER_2:
2282 case TOOL_CTRL_ID_PLAYER_3:
2285 case TOOL_CTRL_ID_PLAYER_4:
2296 case EVENT_KEYPRESS:
2297 switch(GetEventKey((KeyEvent *)&event, TRUE))
2310 if (req_state & REQ_PLAYER)
2314 case EVENT_KEYRELEASE:
2315 ClearPlayerAction();
2319 HandleOtherEvents(&event);
2323 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2325 int joy = AnyJoystick();
2327 if (joy & JOY_BUTTON_1)
2329 else if (joy & JOY_BUTTON_2)
2335 /* don't eat all CPU time */
2339 if (game_status != GAME_MODE_MAIN)
2344 if (!(req_state & REQ_STAY_OPEN))
2346 CloseDoor(DOOR_CLOSE_1);
2348 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
2350 BlitBitmap(bitmap_db_door, bitmap_db_door,
2351 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
2352 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2353 OpenDoor(DOOR_OPEN_1);
2359 SetDrawBackgroundMask(REDRAW_FIELD);
2361 #if defined(NETWORK_AVALIABLE)
2362 /* continue network game after request */
2363 if (options.network &&
2364 game_status == GAME_MODE_PLAYING &&
2365 req_state & REQUEST_WAIT_FOR)
2366 SendToServer_ContinuePlaying();
2370 /* restore deactivated drawing when quick-loading level tape recording */
2371 if (tape.playing && tape.deactivate_display)
2372 TapeDeactivateDisplayOn();
2378 unsigned int OpenDoor(unsigned int door_state)
2380 unsigned int new_door_state;
2382 if (door_state & DOOR_COPY_BACK)
2384 BlitBitmap(bitmap_db_door, bitmap_db_door,
2385 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
2386 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2387 door_state &= ~DOOR_COPY_BACK;
2390 new_door_state = MoveDoor(door_state);
2392 return(new_door_state);
2395 unsigned int CloseDoor(unsigned int door_state)
2397 unsigned int new_door_state;
2399 BlitBitmap(backbuffer, bitmap_db_door,
2400 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2401 BlitBitmap(backbuffer, bitmap_db_door,
2402 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2404 new_door_state = MoveDoor(door_state);
2406 return(new_door_state);
2409 unsigned int GetDoorState()
2411 return MoveDoor(DOOR_GET_STATE);
2414 unsigned int SetDoorState(unsigned int door_state)
2416 return MoveDoor(door_state | DOOR_SET_STATE);
2419 unsigned int MoveDoor(unsigned int door_state)
2421 static int door1 = DOOR_OPEN_1;
2422 static int door2 = DOOR_CLOSE_2;
2423 unsigned long door_delay = 0;
2424 unsigned long door_delay_value;
2427 if (door_state == DOOR_GET_STATE)
2428 return(door1 | door2);
2430 if (door_state & DOOR_SET_STATE)
2432 if (door_state & DOOR_ACTION_1)
2433 door1 = door_state & DOOR_ACTION_1;
2434 if (door_state & DOOR_ACTION_2)
2435 door2 = door_state & DOOR_ACTION_2;
2437 return(door1 | door2);
2440 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2441 door_state &= ~DOOR_OPEN_1;
2442 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2443 door_state &= ~DOOR_CLOSE_1;
2444 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2445 door_state &= ~DOOR_OPEN_2;
2446 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2447 door_state &= ~DOOR_CLOSE_2;
2449 door_delay_value = (door_state & DOOR_ACTION_1 ? door_1.step_delay :
2452 if (setup.quick_doors)
2454 stepsize = 20; /* must be choosen to always draw last frame */
2455 door_delay_value = 0;
2458 StopSound(SND_DOOR_OPENING);
2459 StopSound(SND_DOOR_CLOSING);
2463 if (global.autoplay_leveldir)
2465 door_state |= DOOR_NO_DELAY;
2466 door_state &= ~DOOR_CLOSE_ALL;
2469 if (door_state & DOOR_ACTION)
2471 boolean door_1_done = !(door_state & DOOR_ACTION_1);
2472 boolean door_2_done = !(door_state & DOOR_ACTION_2);
2473 int start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2474 int end = (door_state & DOOR_ACTION_1 &&
2475 door_1.anim_mode == ANIM_VERTICAL ? DYSIZE : DXSIZE);
2478 if (!(door_state & DOOR_NO_DELAY) && !setup.quick_doors)
2480 /* opening door sound has priority over simultaneously closing door */
2481 if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
2482 PlaySoundStereo(SND_DOOR_OPENING, SOUND_MIDDLE);
2483 else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
2484 PlaySoundStereo(SND_DOOR_CLOSING, SOUND_MIDDLE);
2487 for (x = start; x <= end && !(door_1_done && door_2_done); x += stepsize)
2489 Bitmap *bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2490 GC gc = bitmap->stored_clip_gc;
2492 if (door_state & DOOR_ACTION_1)
2494 int a = MIN(x * door_1.step_offset, end);
2495 int i = (door_state & DOOR_OPEN_1 ? end - a : a);
2499 BlitBitmap(bitmap_db_door, drawto,
2500 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i / 2,
2501 DXSIZE,DYSIZE - i / 2, DX, DY);
2503 ClearRectangle(drawto, DX, DY + DYSIZE - i / 2, DXSIZE, i / 2);
2506 if (door_1.anim_mode == ANIM_HORIZONTAL && x <= DXSIZE)
2508 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
2509 int dst1_x = DX + DXSIZE - i, dst1_y = DY;
2510 int src2_x = DXSIZE - i, src2_y = DOOR_GFX_PAGEY1;
2511 int dst2_x = DX, dst2_y = DY;
2512 int width = i, height = DYSIZE;
2514 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2515 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2518 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2519 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2522 else if (door_1.anim_mode == ANIM_VERTICAL && x <= DYSIZE)
2524 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
2525 int dst1_x = DX, dst1_y = DY + DYSIZE - i;
2526 int src2_x = 0, src2_y = DOOR_GFX_PAGEY1 + DYSIZE - i;
2527 int dst2_x = DX, dst2_y = DY;
2528 int width = DXSIZE, height = i;
2530 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2531 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2534 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2535 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2538 else if (x <= DXSIZE) /* ANIM_DEFAULT */
2540 int j = (door_1.anim_mode == ANIM_DEFAULT ? (DXSIZE - i) / 3 : 0);
2542 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2543 BlitBitmapMasked(bitmap, drawto,
2544 DXSIZE, DOOR_GFX_PAGEY1, i, 77,
2545 DX + DXSIZE - i, DY + j);
2546 BlitBitmapMasked(bitmap, drawto,
2547 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
2548 DX + DXSIZE - i, DY + 140 + j);
2549 SetClipOrigin(bitmap, gc, DX - DXSIZE + i,
2550 DY - (DOOR_GFX_PAGEY1 + j));
2551 BlitBitmapMasked(bitmap, drawto,
2552 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
2554 BlitBitmapMasked(bitmap, drawto,
2555 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
2558 BlitBitmapMasked(bitmap, drawto,
2559 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2561 BlitBitmapMasked(bitmap, drawto,
2562 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2564 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2565 BlitBitmapMasked(bitmap, drawto,
2566 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2567 DX + DXSIZE - i, DY + 77 + j);
2568 BlitBitmapMasked(bitmap, drawto,
2569 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2570 DX + DXSIZE - i, DY + 203 + j);
2573 redraw_mask |= REDRAW_DOOR_1;
2574 door_1_done = (a == end);
2577 if (door_state & DOOR_ACTION_2)
2579 int a = MIN(x * door_2.step_offset, VXSIZE);
2580 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - a : a);
2584 BlitBitmap(bitmap_db_door, drawto,
2585 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i / 2,
2586 VXSIZE, VYSIZE - i / 2, VX, VY);
2588 ClearRectangle(drawto, VX, VY + VYSIZE - i / 2, VXSIZE, i / 2);
2591 if (door_2.anim_mode == ANIM_HORIZONTAL && x <= VXSIZE)
2593 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
2594 int dst1_x = VX + VXSIZE - i, dst1_y = VY;
2595 int src2_x = VXSIZE - i, src2_y = DOOR_GFX_PAGEY2;
2596 int dst2_x = VX, dst2_y = VY;
2597 int width = i, height = VYSIZE;
2599 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2600 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2603 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2604 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2607 else if (door_2.anim_mode == ANIM_VERTICAL && x <= VYSIZE)
2609 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
2610 int dst1_x = VX, dst1_y = VY + VYSIZE - i;
2611 int src2_x = 0, src2_y = DOOR_GFX_PAGEY2 + VYSIZE - i;
2612 int dst2_x = VX, dst2_y = VY;
2613 int width = VXSIZE, height = i;
2615 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2616 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2619 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2620 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2623 else if (x <= VXSIZE) /* ANIM_DEFAULT */
2625 int j = (door_2.anim_mode == ANIM_DEFAULT ? (VXSIZE - i) / 3 : 0);
2627 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2628 BlitBitmapMasked(bitmap, drawto,
2629 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
2630 VX + VXSIZE - i, VY + j);
2631 SetClipOrigin(bitmap, gc,
2632 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2633 BlitBitmapMasked(bitmap, drawto,
2634 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
2637 BlitBitmapMasked(bitmap, drawto,
2638 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2639 i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
2640 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2641 BlitBitmapMasked(bitmap, drawto,
2642 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2644 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2647 redraw_mask |= REDRAW_DOOR_2;
2648 door_2_done = (a == VXSIZE);
2653 if (game_status == GAME_MODE_MAIN)
2656 if (!(door_state & DOOR_NO_DELAY))
2657 WaitUntilDelayReached(&door_delay, door_delay_value);
2662 if (setup.quick_doors)
2664 StopSound(SND_DOOR_OPENING);
2665 StopSound(SND_DOOR_CLOSING);
2669 if (door_state & DOOR_ACTION_1)
2670 door1 = door_state & DOOR_ACTION_1;
2671 if (door_state & DOOR_ACTION_2)
2672 door2 = door_state & DOOR_ACTION_2;
2674 return (door1 | door2);
2677 void DrawSpecialEditorDoor()
2679 /* draw bigger toolbox window */
2680 BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
2681 DOOR_GFX_PAGEX7, 0, EXSIZE + 8, 8,
2683 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2684 EX - 4, VY - 4, EXSIZE + 8, EYSIZE - VYSIZE + 4,
2687 redraw_mask |= REDRAW_ALL;
2690 void UndrawSpecialEditorDoor()
2692 /* draw normal tape recorder window */
2693 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2694 EX - 4, EY - 12, EXSIZE + 8, EYSIZE - VYSIZE + 12,
2697 redraw_mask |= REDRAW_ALL;
2701 /* ---------- new tool button stuff ---------------------------------------- */
2703 /* graphic position values for tool buttons */
2704 #define TOOL_BUTTON_YES_XPOS 2
2705 #define TOOL_BUTTON_YES_YPOS 250
2706 #define TOOL_BUTTON_YES_GFX_YPOS 0
2707 #define TOOL_BUTTON_YES_XSIZE 46
2708 #define TOOL_BUTTON_YES_YSIZE 28
2709 #define TOOL_BUTTON_NO_XPOS 52
2710 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2711 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2712 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2713 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2714 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2715 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2716 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2717 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2718 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2719 #define TOOL_BUTTON_PLAYER_XSIZE 30
2720 #define TOOL_BUTTON_PLAYER_YSIZE 30
2721 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2722 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2723 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2724 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2725 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2726 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2727 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2728 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2729 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2730 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2731 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2732 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2733 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2734 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2735 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2736 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2737 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2738 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2739 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2740 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2749 } toolbutton_info[NUM_TOOL_BUTTONS] =
2752 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2753 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2754 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2759 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2760 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2761 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2766 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2767 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2768 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2769 TOOL_CTRL_ID_CONFIRM,
2773 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2774 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2775 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2776 TOOL_CTRL_ID_PLAYER_1,
2780 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2781 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2782 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2783 TOOL_CTRL_ID_PLAYER_2,
2787 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2788 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2789 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2790 TOOL_CTRL_ID_PLAYER_3,
2794 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2795 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2796 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2797 TOOL_CTRL_ID_PLAYER_4,
2802 void CreateToolButtons()
2806 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2808 Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2809 Bitmap *deco_bitmap = None;
2810 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2811 struct GadgetInfo *gi;
2812 unsigned long event_mask;
2813 int gd_xoffset, gd_yoffset;
2814 int gd_x1, gd_x2, gd_y;
2817 event_mask = GD_EVENT_RELEASED;
2819 gd_xoffset = toolbutton_info[i].xpos;
2820 gd_yoffset = toolbutton_info[i].ypos;
2821 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2822 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2823 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2825 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2827 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
2829 getMiniGraphicSource(PLAYER_NR_GFX(IMG_PLAYER_1, player_nr),
2830 &deco_bitmap, &deco_x, &deco_y);
2831 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2832 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2835 gi = CreateGadget(GDI_CUSTOM_ID, id,
2836 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2837 GDI_X, DX + toolbutton_info[i].x,
2838 GDI_Y, DY + toolbutton_info[i].y,
2839 GDI_WIDTH, toolbutton_info[i].width,
2840 GDI_HEIGHT, toolbutton_info[i].height,
2841 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2842 GDI_STATE, GD_BUTTON_UNPRESSED,
2843 GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
2844 GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
2845 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
2846 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2847 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2848 GDI_DECORATION_SHIFTING, 1, 1,
2849 GDI_EVENT_MASK, event_mask,
2850 GDI_CALLBACK_ACTION, HandleToolButtons,
2854 Error(ERR_EXIT, "cannot create gadget");
2856 tool_gadget[id] = gi;
2860 void FreeToolButtons()
2864 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2865 FreeGadget(tool_gadget[i]);
2868 static void UnmapToolButtons()
2872 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2873 UnmapGadget(tool_gadget[i]);
2876 static void HandleToolButtons(struct GadgetInfo *gi)
2878 request_gadget_id = gi->custom_id;
2881 int get_next_element(int element)
2885 case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL;
2886 case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY;
2887 case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL;
2888 case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_ACTIVE;
2889 case EL_BD_MAGIC_WALL_FILLING: return EL_BD_MAGIC_WALL_FULL;
2890 case EL_BD_MAGIC_WALL_EMPTYING: return EL_BD_MAGIC_WALL_ACTIVE;
2891 case EL_AMOEBA_DROPPING: return EL_AMOEBA_WET;
2893 default: return element;
2897 int el_act_dir2img(int element, int action, int direction)
2899 element = GFX_ELEMENT(element);
2900 direction = MV_DIR_BIT(direction); /* default: MV_NO_MOVING => MV_DOWN */
2902 return element_info[element].direction_graphic[action][direction];
2905 static int el_act_dir2crm(int element, int action, int direction)
2907 element = GFX_ELEMENT(element);
2908 direction = MV_DIR_BIT(direction); /* default: MV_NO_MOVING => MV_DOWN */
2910 return element_info[element].direction_crumbled[action][direction];
2913 int el_act2img(int element, int action)
2915 element = GFX_ELEMENT(element);
2917 return element_info[element].graphic[action];
2920 int el_act2crm(int element, int action)
2922 element = GFX_ELEMENT(element);
2924 return element_info[element].crumbled[action];
2927 int el_dir2img(int element, int direction)
2929 element = GFX_ELEMENT(element);
2931 return el_act_dir2img(element, ACTION_DEFAULT, direction);
2934 int el2baseimg(int element)
2936 return element_info[element].graphic[ACTION_DEFAULT];
2939 int el2img(int element)
2941 element = GFX_ELEMENT(element);
2943 return element_info[element].graphic[ACTION_DEFAULT];
2946 int el2edimg(int element)
2948 element = GFX_ELEMENT(element);
2950 return element_info[element].special_graphic[GFX_SPECIAL_ARG_EDITOR];
2953 int el2preimg(int element)
2955 element = GFX_ELEMENT(element);
2957 return element_info[element].special_graphic[GFX_SPECIAL_ARG_PREVIEW];