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 int getGraphicAnimationPhase(int, int, int);
36 static void UnmapToolButtons();
37 static void HandleToolButtons(struct GadgetInfo *);
39 static struct GadgetInfo *tool_gadget[NUM_TOOL_BUTTONS];
40 static int request_gadget_id = -1;
42 void SetDrawtoField(int mode)
44 if (mode == DRAW_BUFFERED && setup.soft_scrolling)
55 drawto_field = fieldbuffer;
57 else /* DRAW_DIRECT, DRAW_BACKBUFFER */
68 drawto_field = (mode == DRAW_DIRECT ? window : backbuffer);
72 void RedrawPlayfield(boolean force_redraw, int x, int y, int width, int height)
74 if (game_status == PLAYING)
80 width = gfx.sxsize + 2 * TILEX;
81 height = gfx.sysize + 2 * TILEY;
84 if (force_redraw || setup.direct_draw)
87 int x1 = (x - SX) / TILEX, y1 = (y - SY) / TILEY;
88 int x2 = (x - SX + width) / TILEX, y2 = (y - SY + height) / TILEY;
90 if (setup.direct_draw)
91 SetDrawtoField(DRAW_BACKBUFFER);
93 for(xx=BX1; xx<=BX2; xx++)
94 for(yy=BY1; yy<=BY2; yy++)
95 if (xx >= x1 && xx <= x2 && yy >= y1 && yy <= y2)
96 DrawScreenField(xx, yy);
99 if (setup.direct_draw)
100 SetDrawtoField(DRAW_DIRECT);
103 if (setup.soft_scrolling)
105 int fx = FX, fy = FY;
107 fx += (ScreenMovDir & (MV_LEFT|MV_RIGHT) ? ScreenGfxPos : 0);
108 fy += (ScreenMovDir & (MV_UP|MV_DOWN) ? ScreenGfxPos : 0);
110 BlitBitmap(fieldbuffer, backbuffer, fx,fy, SXSIZE,SYSIZE, SX,SY);
114 BlitBitmap(drawto, window, x, y, width, height, x, y);
120 DrawBuffer *buffer = (drawto_field == window ? backbuffer : drawto_field);
122 if (setup.direct_draw && game_status == PLAYING)
123 redraw_mask &= ~REDRAW_MAIN;
125 if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD)
126 redraw_mask |= REDRAW_FIELD;
128 if (redraw_mask & REDRAW_FIELD)
129 redraw_mask &= ~REDRAW_TILES;
131 if (redraw_mask == REDRAW_NONE)
134 if (global.fps_slowdown && game_status == PLAYING)
136 static boolean last_frame_skipped = FALSE;
137 boolean skip_even_when_not_scrolling = TRUE;
138 boolean just_scrolling = (ScreenMovDir != 0);
139 boolean verbose = FALSE;
141 if (global.fps_slowdown_factor > 1 &&
142 (FrameCounter % global.fps_slowdown_factor) &&
143 (just_scrolling || skip_even_when_not_scrolling))
145 redraw_mask &= ~REDRAW_MAIN;
147 last_frame_skipped = TRUE;
150 printf("FRAME SKIPPED\n");
154 if (last_frame_skipped)
155 redraw_mask |= REDRAW_FIELD;
157 last_frame_skipped = FALSE;
160 printf("frame not skipped\n");
164 /* synchronize X11 graphics at this point; if we would synchronize the
165 display immediately after the buffer switching (after the XFlush),
166 this could mean that we have to wait for the graphics to complete,
167 although we could go on doing calculations for the next frame */
171 if (redraw_mask & REDRAW_ALL)
173 BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
177 if (redraw_mask & REDRAW_FIELD)
179 if (game_status != PLAYING || redraw_mask & REDRAW_FROM_BACKBUFFER)
181 BlitBitmap(backbuffer, window,
182 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE, REAL_SX, REAL_SY);
186 int fx = FX, fy = FY;
188 if (setup.soft_scrolling)
190 fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
191 fy += (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
194 if (setup.soft_scrolling ||
195 ABS(ScreenMovPos) + ScrollStepSize == TILEX ||
196 ABS(ScreenMovPos) == ScrollStepSize ||
197 redraw_tiles > REDRAWTILES_THRESHOLD)
199 BlitBitmap(buffer, window, fx, fy, SXSIZE, SYSIZE, SX, SY);
203 printf("redrawing all (ScreenGfxPos == %d) because %s\n",
205 (setup.soft_scrolling ?
206 "setup.soft_scrolling" :
207 ABS(ScreenGfxPos) + ScrollStepSize == TILEX ?
208 "ABS(ScreenGfxPos) + ScrollStepSize == TILEX" :
209 ABS(ScreenGfxPos) == ScrollStepSize ?
210 "ABS(ScreenGfxPos) == ScrollStepSize" :
211 "redraw_tiles > REDRAWTILES_THRESHOLD"));
217 redraw_mask &= ~REDRAW_MAIN;
220 if (redraw_mask & REDRAW_DOORS)
222 if (redraw_mask & REDRAW_DOOR_1)
223 BlitBitmap(backbuffer, window, DX, DY, DXSIZE, DYSIZE, DX, DY);
224 if (redraw_mask & REDRAW_DOOR_2)
226 if ((redraw_mask & REDRAW_DOOR_2) == REDRAW_DOOR_2)
227 BlitBitmap(backbuffer, window, VX,VY, VXSIZE,VYSIZE, VX,VY);
230 if (redraw_mask & REDRAW_VIDEO_1)
231 BlitBitmap(backbuffer, window,
232 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS,
233 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
234 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS);
235 if (redraw_mask & REDRAW_VIDEO_2)
236 BlitBitmap(backbuffer, window,
237 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS,
238 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
239 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS);
240 if (redraw_mask & REDRAW_VIDEO_3)
241 BlitBitmap(backbuffer, window,
242 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS,
243 VIDEO_CONTROL_XSIZE,VIDEO_CONTROL_YSIZE,
244 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS);
247 if (redraw_mask & REDRAW_DOOR_3)
248 BlitBitmap(backbuffer, window, EX, EY, EXSIZE, EYSIZE, EX, EY);
249 redraw_mask &= ~REDRAW_DOORS;
252 if (redraw_mask & REDRAW_MICROLEVEL)
254 BlitBitmap(backbuffer, window,
255 MICROLEV_XPOS, MICROLEV_YPOS, MICROLEV_XSIZE, MICROLEV_YSIZE,
256 MICROLEV_XPOS, MICROLEV_YPOS);
257 BlitBitmap(backbuffer, window,
258 SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE,
259 SX, MICROLABEL_YPOS);
260 redraw_mask &= ~REDRAW_MICROLEVEL;
263 if (redraw_mask & REDRAW_TILES)
265 for(x=0; x<SCR_FIELDX; x++)
266 for(y=0; y<SCR_FIELDY; y++)
267 if (redraw[redraw_x1 + x][redraw_y1 + y])
268 BlitBitmap(buffer, window,
269 FX + x * TILEX, FX + y * TILEY, TILEX, TILEY,
270 SX + x * TILEX, SY + y * TILEY);
273 if (redraw_mask & REDRAW_FPS) /* display frames per second */
278 sprintf(info1, " (only every %d. frame)", global.fps_slowdown_factor);
279 if (!global.fps_slowdown)
282 sprintf(text, "%.1f fps%s", global.frames_per_second, info1);
283 DrawTextExt(window, SX, SY, text, FS_SMALL, FC_YELLOW);
288 for(x=0; x<MAX_BUF_XSIZE; x++)
289 for(y=0; y<MAX_BUF_YSIZE; y++)
292 redraw_mask = REDRAW_NONE;
298 long fading_delay = 300;
300 if (setup.fading && (redraw_mask & REDRAW_FIELD))
307 ClearRectangle(window, REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
310 for(i=0;i<2*FULL_SYSIZE;i++)
312 for(y=0;y<FULL_SYSIZE;y++)
314 BlitBitmap(backbuffer, window,
315 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
323 for(i=1;i<FULL_SYSIZE;i+=2)
324 BlitBitmap(backbuffer, window,
325 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
331 SetClipOrigin(clip_gc[PIX_FADEMASK], 0, 0);
332 BlitBitmapMasked(backbuffer, window,
333 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
338 SetClipOrigin(clip_gc[PIX_FADEMASK], -1, -1);
339 BlitBitmapMasked(backbuffer, window,
340 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
345 SetClipOrigin(clip_gc[PIX_FADEMASK], 0, -1);
346 BlitBitmapMasked(backbuffer, window,
347 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
352 SetClipOrigin(clip_gc[PIX_FADEMASK], -1, 0);
353 BlitBitmapMasked(backbuffer, window,
354 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
359 redraw_mask &= ~REDRAW_MAIN;
368 ClearRectangle(backbuffer, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
370 if (setup.soft_scrolling && game_status == PLAYING)
372 ClearRectangle(fieldbuffer, 0, 0, FXSIZE, FYSIZE);
373 SetDrawtoField(DRAW_BUFFERED);
376 SetDrawtoField(DRAW_BACKBUFFER);
378 if (setup.direct_draw && game_status == PLAYING)
380 ClearRectangle(window, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
381 SetDrawtoField(DRAW_DIRECT);
384 redraw_mask |= REDRAW_FIELD;
387 void MarkTileDirty(int x, int y)
389 int xx = redraw_x1 + x;
390 int yy = redraw_y1 + y;
395 redraw[xx][yy] = TRUE;
396 redraw_mask |= REDRAW_TILES;
399 void SetBorderElement()
403 BorderElement = EL_EMPTY;
405 for(y=0; y<lev_fieldy && BorderElement == EL_EMPTY; y++)
407 for(x=0; x<lev_fieldx; x++)
409 if (!IS_MASSIVE(Feld[x][y]))
410 BorderElement = EL_STEELWALL;
412 if (y != 0 && y != lev_fieldy - 1 && x != lev_fieldx - 1)
418 void DrawAllPlayers()
422 for(i=0; i<MAX_PLAYERS; i++)
423 if (stored_player[i].active)
424 DrawPlayer(&stored_player[i]);
427 void DrawPlayerField(int x, int y)
429 if (!IS_PLAYER(x, y))
432 DrawPlayer(PLAYERINFO(x, y));
435 void DrawPlayer(struct PlayerInfo *player)
437 int jx = player->jx, jy = player->jy;
438 int last_jx = player->last_jx, last_jy = player->last_jy;
439 int next_jx = jx + (jx - last_jx), next_jy = jy + (jy - last_jy);
440 int sx = SCREENX(jx), sy = SCREENY(jy);
441 int sxx = 0, syy = 0;
442 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
445 boolean player_is_moving = (last_jx != jx || last_jy != jy ? TRUE : FALSE);
447 if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
451 if (!IN_LEV_FIELD(jx,jy))
453 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
454 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
455 printf("DrawPlayerField(): This should never happen!\n");
460 if (element == EL_EXPLOSION)
463 /* draw things in the field the player is leaving, if needed */
465 if (player_is_moving)
467 if (Store[last_jx][last_jy] && IS_DRAWABLE(last_element))
469 DrawLevelElement(last_jx, last_jy, Store[last_jx][last_jy]);
471 if (last_element == EL_DYNAMITE_ACTIVE)
472 DrawDynamite(last_jx, last_jy);
474 DrawLevelFieldThruMask(last_jx, last_jy);
476 else if (last_element == EL_DYNAMITE_ACTIVE)
477 DrawDynamite(last_jx, last_jy);
479 DrawLevelField(last_jx, last_jy);
481 if (player->Pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
485 if (Feld[next_jx][next_jy] == EL_SOKOBAN_FIELD_FULL)
486 DrawLevelElement(next_jx, next_jy, EL_SOKOBAN_FIELD_EMPTY);
488 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
491 DrawLevelField(next_jx, next_jy);
495 if (!IN_SCR_FIELD(sx, sy))
498 if (setup.direct_draw)
499 SetDrawtoField(DRAW_BUFFERED);
501 /* draw things behind the player, if needed */
504 DrawLevelElement(jx, jy, Store[jx][jy]);
505 else if (!IS_ACTIVE_BOMB(element))
506 DrawLevelField(jx, jy);
508 DrawLevelElement(jx, jy, EL_EMPTY);
510 /* draw player himself */
512 if (game.emulation == EMU_SUPAPLEX)
514 static int last_dir = MV_LEFT;
515 int action = (player->programmed_action ? player->programmed_action :
517 boolean action_moving =
519 ((action & (MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN)) &&
520 !(action & ~(MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN))));
522 graphic = IMG_SP_MURPHY;
526 if (player->MovDir == MV_LEFT)
527 graphic = IMG_SP_MURPHY_LEFT_PUSHING;
528 else if (player->MovDir == MV_RIGHT)
529 graphic = IMG_SP_MURPHY_RIGHT_PUSHING;
530 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
531 graphic = IMG_SP_MURPHY_LEFT_PUSHING;
532 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
533 graphic = IMG_SP_MURPHY_RIGHT_PUSHING;
535 else if (player->snapped)
537 if (player->MovDir == MV_LEFT)
538 graphic = IMG_SP_MURPHY_LEFT_SNAPPING;
539 else if (player->MovDir == MV_RIGHT)
540 graphic = IMG_SP_MURPHY_RIGHT_SNAPPING;
541 else if (player->MovDir == MV_UP)
542 graphic = IMG_SP_MURPHY_UP_SNAPPING;
543 else if (player->MovDir == MV_DOWN)
544 graphic = IMG_SP_MURPHY_DOWN_SNAPPING;
546 else if (action_moving)
548 if (player->MovDir == MV_LEFT)
549 graphic = IMG_SP_MURPHY_LEFT_MOVING;
550 else if (player->MovDir == MV_RIGHT)
551 graphic = IMG_SP_MURPHY_RIGHT_MOVING;
552 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
553 graphic = IMG_SP_MURPHY_LEFT_MOVING;
554 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
555 graphic = IMG_SP_MURPHY_RIGHT_MOVING;
557 graphic = IMG_SP_MURPHY_LEFT_MOVING;
559 frame = getGraphicAnimationFrame(graphic, -1);
562 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
563 last_dir = player->MovDir;
567 if (player->MovDir == MV_LEFT)
568 graphic = (player->Pushing ? IMG_PLAYER1_LEFT_PUSHING :
569 player->is_moving ? IMG_PLAYER1_LEFT_MOVING :
571 else if (player->MovDir == MV_RIGHT)
572 graphic = (player->Pushing ? IMG_PLAYER1_RIGHT_PUSHING :
573 player->is_moving ? IMG_PLAYER1_RIGHT_MOVING :
575 else if (player->MovDir == MV_UP)
576 graphic = (player->Pushing ? IMG_PLAYER1_UP_PUSHING :
577 player->is_moving ? IMG_PLAYER1_UP_MOVING :
579 else /* MV_DOWN || MV_NO_MOVING */
580 graphic = (player->Pushing ? IMG_PLAYER1_DOWN_PUSHING :
581 player->is_moving ? IMG_PLAYER1_DOWN_MOVING :
584 graphic = PLAYER_NR_GFX(graphic, player->index_nr);
587 frame = player->Frame;
589 frame = getGraphicAnimationFrame(graphic, player->Frame);
595 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
596 sxx = player->GfxPos;
598 syy = player->GfxPos;
601 if (!setup.soft_scrolling && ScreenMovPos)
606 printf("-> %d\n", player->Frame);
609 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
611 if (SHIELD_ON(player))
613 int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
614 IMG_SHIELD_NORMAL_ACTIVE);
615 int frame = getGraphicAnimationFrame(graphic, -1);
617 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
621 if (player->Pushing && player->GfxPos)
623 if (player->Pushing && player_is_moving)
626 int px = SCREENX(next_jx), py = SCREENY(next_jy);
628 if (element == EL_SOKOBAN_FIELD_EMPTY ||
629 Feld[next_jx][next_jy] == EL_SOKOBAN_FIELD_FULL)
630 DrawGraphicShiftedThruMask(px, py, sxx, syy, GFX_SOKOBAN_OBJEKT, 0,
634 int element = Feld[next_jx][next_jy];
635 int graphic = el2img(element);
640 if ((element == EL_ROCK ||
641 element == EL_BD_ROCK ||
642 element == EL_SP_ZONK) && sxx)
644 graphic = el_dir_act2img(element, player->MovDir, GFX_ACTION_MOVING);
646 frame = getGraphicAnimationFrame(graphic, player->GfxPos);
648 frame = getGraphicAnimationFrame(graphic, player->Frame);
652 printf("-> %d [%d]\n", player->Frame, player->GfxPos);
657 if (player->MovDir == MV_LEFT)
662 frame = (player->GfxPos / (TILEX / 4));
664 if (player->MovDir == MV_RIGHT)
665 frame = (frame + 4) % 4;
669 DrawGraphicShifted(px, py, sxx, syy, graphic, frame,
670 NO_CUTTING, NO_MASKING);
674 /* draw things in front of player (active dynamite or dynabombs) */
676 if (IS_ACTIVE_BOMB(element))
678 graphic = el2img(element);
681 if (element == EL_DYNAMITE_ACTIVE)
683 if ((frame = (96 - MovDelay[jx][jy]) / 12) > 6)
688 if ((frame = ((96 - MovDelay[jx][jy]) / 6) % 8) > 3)
692 frame = getGraphicAnimationFrame(graphic, 96 - MovDelay[jx][jy]);
695 if (game.emulation == EMU_SUPAPLEX)
696 DrawGraphic(sx, sy, GFX_SP_DISK_RED, 0);
698 DrawGraphicThruMask(sx, sy, graphic, frame);
701 if (player_is_moving && last_element == EL_EXPLOSION)
703 int graphic = IMG_EXPLOSION;
704 int phase = Frame[last_jx][last_jy] - 1;
705 int delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2);
706 int frame = (phase / delay - 1);
708 if (game.emulation == EMU_SUPAPLEX)
709 graphic = (Store[last_jx][last_jy] == EL_SP_INFOTRON ?
710 IMG_SP_EXPLOSION_INFOTRON :
714 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy), graphic, frame);
717 /* draw elements that stay over the player */
718 /* handle the field the player is leaving ... */
719 if (player_is_moving && IS_OVER_PLAYER(last_element))
720 DrawLevelField(last_jx, last_jy);
722 /* ... and the field the player is entering */
723 if (IS_OVER_PLAYER(element))
724 DrawLevelField(jx, jy);
726 if (setup.direct_draw)
728 int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
729 int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
730 int x_size = TILEX * (1 + ABS(jx - last_jx));
731 int y_size = TILEY * (1 + ABS(jy - last_jy));
733 BlitBitmap(drawto_field, window,
734 dest_x, dest_y, x_size, y_size, dest_x, dest_y);
735 SetDrawtoField(DRAW_DIRECT);
738 MarkTileDirty(sx,sy);
741 static int getGraphicAnimationPhase(int frames, int delay, int mode)
745 if (mode & ANIM_PINGPONG)
747 int max_anim_frames = 2 * frames - 2;
749 phase = (FrameCounter % (delay * max_anim_frames)) / delay;
750 phase = (phase < frames ? phase : max_anim_frames - phase);
753 phase = (FrameCounter % (delay * frames)) / delay;
755 if (mode & ANIM_REVERSE)
761 int getGraphicAnimationFrame(int graphic, int sync_frame)
763 int num_frames = new_graphic_info[graphic].anim_frames;
764 int delay = new_graphic_info[graphic].anim_delay;
765 int mode = new_graphic_info[graphic].anim_mode;
768 /* animation synchronized with global frame counter, not move position */
769 if (new_graphic_info[graphic].anim_global_sync || sync_frame < 0)
770 sync_frame = FrameCounter;
772 sync_frame += new_graphic_info[graphic].anim_start_frame * delay;
774 if (mode & ANIM_LOOP) /* normal, looping animation */
776 frame = (sync_frame % (delay * num_frames)) / delay;
778 else if (mode & ANIM_LINEAR) /* normal, non-looping animation */
780 frame = sync_frame / delay;
782 if (frame > num_frames - 1)
783 frame = num_frames - 1;
785 else if (mode & ANIM_PINGPONG) /* use border frames once */
787 int max_anim_frames = 2 * num_frames - 2;
789 frame = (sync_frame % (delay * max_anim_frames)) / delay;
790 frame = (frame < num_frames ? frame : max_anim_frames - frame);
792 else if (mode & ANIM_PINGPONG2) /* use border frames twice */
794 int max_anim_frames = 2 * num_frames;
796 frame = (sync_frame % (delay * max_anim_frames)) / delay;
797 frame = (frame < num_frames ? frame : max_anim_frames - frame - 1);
800 if (mode & ANIM_REVERSE) /* use reverse animation direction */
801 frame = num_frames - frame - 1;
806 void DrawGraphicAnimationExt(int x, int y, int graphic, int mask_mode)
809 int delay = new_graphic_info[graphic].anim_delay;
811 if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
813 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
816 int frame = getGraphicAnimationFrame(graphic, -1);
818 if (mask_mode == USE_MASKING)
819 DrawGraphicThruMask(SCREENX(x), SCREENY(y), graphic, frame);
821 DrawGraphic(SCREENX(x), SCREENY(y), graphic, frame);
826 void DrawOldGraphicAnimation(int x, int y, int graphic,
827 int frames, int delay, int mode)
829 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, NO_MASKING);
833 void DrawGraphicAnimation(int x, int y, int graphic)
835 DrawGraphicAnimationExt(x, y, graphic, NO_MASKING);
839 void getOldGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
841 if (graphic >= 0 && graphic_info[graphic].bitmap != NULL)
843 *bitmap = graphic_info[graphic].bitmap;
844 *x = graphic_info[graphic].src_x;
845 *y = graphic_info[graphic].src_y;
847 else if (graphic >= GFX_START_ROCKSELEMENTS &&
848 graphic <= GFX_END_ROCKSELEMENTS)
850 graphic -= GFX_START_ROCKSELEMENTS;
851 *bitmap = pix[PIX_ELEMENTS];
852 *x = (graphic % GFX_PER_LINE) * TILEX;
853 *y = (graphic / GFX_PER_LINE) * TILEY;
855 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
857 graphic -= GFX_START_ROCKSHEROES;
858 *bitmap = pix[PIX_HEROES];
859 *x = (graphic % HEROES_PER_LINE) * TILEX;
860 *y = (graphic / HEROES_PER_LINE) * TILEY;
862 else if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
864 graphic -= GFX_START_ROCKSSP;
865 *bitmap = pix[PIX_SP];
866 *x = (graphic % SP_PER_LINE) * TILEX;
867 *y = (graphic / SP_PER_LINE) * TILEY;
869 else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
871 graphic -= GFX_START_ROCKSDC;
872 *bitmap = pix[PIX_DC];
873 *x = (graphic % DC_PER_LINE) * TILEX;
874 *y = (graphic / DC_PER_LINE) * TILEY;
876 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
878 graphic -= GFX_START_ROCKSMORE;
879 *bitmap = pix[PIX_MORE];
880 *x = (graphic % MORE_PER_LINE) * TILEX;
881 *y = (graphic / MORE_PER_LINE) * TILEY;
883 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
885 graphic -= GFX_START_ROCKSFONT;
886 *bitmap = pix[PIX_FONT_EM];
887 *x = (graphic % FONT_CHARS_PER_LINE) * TILEX;
888 *y = (graphic / FONT_CHARS_PER_LINE) * TILEY;
892 *bitmap = pix[PIX_SP];
899 void DrawGraphic(int x, int y, int graphic, int frame)
902 if (!IN_SCR_FIELD(x, y))
904 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
905 printf("DrawGraphic(): This should never happen!\n");
910 DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic, frame);
914 void DrawOldGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic)
919 getOldGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
920 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
923 void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
926 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
927 int src_x = new_graphic_info[graphic].src_x;
928 int src_y = new_graphic_info[graphic].src_y;
929 int offset_x = new_graphic_info[graphic].offset_x;
930 int offset_y = new_graphic_info[graphic].offset_y;
932 src_x += frame * offset_x;
933 src_y += frame * offset_y;
935 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
938 void DrawGraphicThruMask(int x, int y, int graphic, int frame)
941 if (!IN_SCR_FIELD(x, y))
943 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
944 printf("DrawGraphicThruMask(): This should never happen!\n");
949 DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY, graphic,
954 void DrawGraphicThruMaskExt(DrawBuffer *d, int dest_x, int dest_y, int graphic,
957 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
958 GC drawing_gc = src_bitmap->stored_clip_gc;
959 int src_x = new_graphic_info[graphic].src_x;
960 int src_y = new_graphic_info[graphic].src_y;
961 int offset_x = new_graphic_info[graphic].offset_x;
962 int offset_y = new_graphic_info[graphic].offset_y;
964 src_x += frame * offset_x;
965 src_y += frame * offset_y;
967 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
968 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dest_x, dest_y);
971 void DrawMiniGraphic(int x, int y, int graphic)
973 DrawMiniGraphicExt(drawto, SX + x * MINI_TILEX,SY + y * MINI_TILEY, graphic);
974 MarkTileDirty(x / 2, y / 2);
977 void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
979 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
981 int mini_starty = src_bitmap->height * 2 / 3;
982 int src_x = mini_startx + new_graphic_info[graphic].src_x / 2;
983 int src_y = mini_starty + new_graphic_info[graphic].src_y / 2;
985 *bitmap = src_bitmap;
990 void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
995 getMiniGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
996 BlitBitmap(src_bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
999 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic, int frame,
1000 int cut_mode, int mask_mode)
1009 int width = TILEX, height = TILEY;
1015 DrawGraphic(x, y, graphic, frame);
1019 if (dx || dy) /* shifted graphic */
1021 if (x < BX1) /* object enters playfield from the left */
1028 else if (x > BX2) /* object enters playfield from the right */
1034 else if (x==BX1 && dx < 0) /* object leaves playfield to the left */
1040 else if (x==BX2 && dx > 0) /* object leaves playfield to the right */
1042 else if (dx) /* general horizontal movement */
1043 MarkTileDirty(x + SIGN(dx), y);
1045 if (y < BY1) /* object enters playfield from the top */
1047 if (cut_mode==CUT_BELOW) /* object completely above top border */
1055 else if (y > BY2) /* object enters playfield from the bottom */
1061 else if (y==BY1 && dy < 0) /* object leaves playfield to the top */
1067 else if (dy > 0 && cut_mode == CUT_ABOVE)
1069 if (y == BY2) /* object completely above bottom border */
1075 MarkTileDirty(x, y + 1);
1076 } /* object leaves playfield to the bottom */
1077 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1079 else if (dy) /* general vertical movement */
1080 MarkTileDirty(x, y + SIGN(dy));
1083 src_bitmap = new_graphic_info[graphic].bitmap;
1084 src_x = new_graphic_info[graphic].src_x;
1085 src_y = new_graphic_info[graphic].src_y;
1086 offset_x = new_graphic_info[graphic].offset_x;
1087 offset_y = new_graphic_info[graphic].offset_y;
1089 drawing_gc = src_bitmap->stored_clip_gc;
1091 src_x += frame * offset_x;
1092 src_y += frame * offset_y;
1097 dest_x = FX + x * TILEX + dx;
1098 dest_y = FY + y * TILEY + dy;
1101 if (!IN_SCR_FIELD(x,y))
1103 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1104 printf("DrawGraphicShifted(): This should never happen!\n");
1109 if (mask_mode == USE_MASKING)
1111 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1112 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
1116 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1122 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
1123 int frame, int cut_mode)
1125 DrawGraphicShifted(x,y, dx,dy, graphic, frame, cut_mode, USE_MASKING);
1129 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1130 int cut_mode, int mask_mode)
1132 int ux = LEVELX(x), uy = LEVELY(y);
1133 int graphic = el2gfx(element);
1134 int phase8 = ABS(MovPos[ux][uy]) / (TILEX / 8);
1135 int phase4 = phase8 / 2;
1136 int phase2 = phase8 / 4;
1137 int dir = MovDir[ux][uy];
1139 if (element == EL_PACMAN || element == EL_BUG || element == EL_SPACESHIP)
1141 graphic += 1 * !phase2;
1145 else if (dir == MV_LEFT)
1147 else if (dir == MV_DOWN)
1150 else if (element == EL_SP_SNIKSNAK)
1153 graphic = GFX_SP_SNIKSNAK_LEFT;
1154 else if (dir == MV_RIGHT)
1155 graphic = GFX_SP_SNIKSNAK_RIGHT;
1156 else if (dir == MV_UP)
1157 graphic = GFX_SP_SNIKSNAK_UP;
1159 graphic = GFX_SP_SNIKSNAK_DOWN;
1161 graphic += (phase8 < 4 ? phase8 : 7 - phase8);
1163 else if (element == EL_SP_ELECTRON)
1165 graphic = GFX2_SP_ELECTRON + getGraphicAnimationPhase(8, 2, ANIM_LOOP);
1167 else if (element == EL_MOLE || element == EL_PENGUIN ||
1168 element == EL_PIG || element == EL_DRAGON)
1171 graphic = (element == EL_MOLE ? GFX_MOLE_LEFT :
1172 element == EL_PENGUIN ? GFX_PINGUIN_LEFT :
1173 element == EL_PIG ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
1174 else if (dir == MV_RIGHT)
1175 graphic = (element == EL_MOLE ? GFX_MOLE_RIGHT :
1176 element == EL_PENGUIN ? GFX_PINGUIN_RIGHT :
1177 element == EL_PIG ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
1178 else if (dir == MV_UP)
1179 graphic = (element == EL_MOLE ? GFX_MOLE_UP :
1180 element == EL_PENGUIN ? GFX_PINGUIN_UP :
1181 element == EL_PIG ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
1183 graphic = (element == EL_MOLE ? GFX_MOLE_DOWN :
1184 element == EL_PENGUIN ? GFX_PINGUIN_DOWN :
1185 element == EL_PIG ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
1189 else if (element == EL_SATELLITE)
1191 graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_LOOP);
1193 else if (element == EL_ACID)
1195 graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_LOOP);
1197 else if (element == EL_BD_BUTTERFLY || element == EL_BD_FIREFLY)
1201 else if (element == EL_BALLOON)
1205 else if ((element == EL_ROCK ||
1206 element == EL_SP_ZONK ||
1207 element == EL_BD_ROCK ||
1208 element == EL_SP_INFOTRON ||
1212 if (uy >= lev_fieldy-1 || !IS_BELT(Feld[ux][uy+1]))
1214 if (element == EL_ROCK ||
1215 element == EL_SP_ZONK ||
1216 element == EL_BD_ROCK)
1219 graphic += (4 - phase4) % 4;
1220 else if (dir == MV_RIGHT)
1223 graphic += phase2 * 2;
1225 else if (element != EL_SP_INFOTRON)
1229 else if (element == EL_MAGIC_WALL_ACTIVE ||
1230 element == EL_MAGIC_WALL_EMPTYING ||
1231 element == EL_BD_MAGIC_WALL_ACTIVE ||
1232 element == EL_BD_MAGIC_WALL_EMPTYING ||
1233 element == EL_MAGIC_WALL_FULL ||
1234 element == EL_BD_MAGIC_WALL_FULL)
1236 graphic += 3 + getGraphicAnimationPhase(4, 4, ANIM_REVERSE);
1238 else if (IS_AMOEBOID(element) || element == EL_AMOEBA_DRIPPING)
1240 graphic = (element == EL_AMOEBA_DEAD ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
1241 graphic += (x + 2 * y + 4) % 4;
1243 else if (element == EL_WALL_GROWING)
1245 boolean links_massiv = FALSE, rechts_massiv = FALSE;
1247 if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
1248 links_massiv = TRUE;
1249 if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
1250 rechts_massiv = TRUE;
1252 if (links_massiv && rechts_massiv)
1253 graphic = GFX_MAUERWERK;
1254 else if (links_massiv)
1255 graphic = GFX_MAUER_R;
1256 else if (rechts_massiv)
1257 graphic = GFX_MAUER_L;
1260 else if ((element == EL_INVISIBLE_STEELWALL ||
1261 element == EL_INVISIBLE_WALL ||
1262 element == EL_INVISIBLE_SAND) && game.light_time_left)
1264 graphic = (element == EL_INVISIBLE_STEELWALL ? GFX_INVISIBLE_STEEL_ON :
1265 element == EL_INVISIBLE_WALL ? GFX_UNSICHTBAR_ON :
1266 GFX_SAND_INVISIBLE_ON);
1271 DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
1272 else if (mask_mode == USE_MASKING)
1273 DrawGraphicThruMask(x, y, graphic);
1275 DrawGraphic(x, y, graphic);
1279 inline static int getFramePosition(int x, int y)
1281 int frame_pos = -1; /* default: global synchronization */
1283 int element = Feld[x][y];
1285 if (element == EL_QUICKSAND_FULL ||
1286 element == EL_MAGIC_WALL_FULL ||
1287 element == EL_BD_MAGIC_WALL_FULL)
1289 else if (IS_MOVING(x, y) || CAN_MOVE(element) || CAN_FALL(element))
1290 frame_pos = ABS(MovPos[x][y]) / (TILEX / 8);
1292 frame_pos = ABS(MovPos[x][y]) / (TILEX / 8);
1298 inline static int getGfxAction(int x, int y)
1300 int gfx_action = GFX_ACTION_DEFAULT;
1303 if (GfxAction[x][y] != GFX_ACTION_DEFAULT)
1304 gfx_action = GfxAction[x][y];
1305 else if (IS_MOVING(x, y))
1306 gfx_action = GFX_ACTION_MOVING;
1308 gfx_action = GfxAction[x][y];
1314 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1315 int cut_mode, int mask_mode)
1317 int ux = LEVELX(x), uy = LEVELY(y);
1318 int move_dir = MovDir[ux][uy];
1319 int move_pos = getFramePosition(ux, uy);
1320 int gfx_action = getGfxAction(ux, uy);
1321 int graphic = el_dir_act2img(element, move_dir, gfx_action);
1322 int frame = getGraphicAnimationFrame(graphic, move_pos);
1324 if (element == EL_WALL_GROWING)
1326 boolean left_stopped = FALSE, right_stopped = FALSE;
1328 if (!IN_LEV_FIELD(ux - 1, uy) || IS_MAUER(Feld[ux - 1][uy]))
1329 left_stopped = TRUE;
1330 if (!IN_LEV_FIELD(ux + 1, uy) || IS_MAUER(Feld[ux + 1][uy]))
1331 right_stopped = TRUE;
1333 if (left_stopped && right_stopped)
1335 else if (left_stopped)
1337 graphic = IMG_WALL_GROWING_ACTIVE_RIGHT;
1338 frame = new_graphic_info[graphic].anim_frames - 1;
1340 else if (right_stopped)
1342 graphic = IMG_WALL_GROWING_ACTIVE_LEFT;
1343 frame = new_graphic_info[graphic].anim_frames - 1;
1346 else if (IS_AMOEBOID(element) || element == EL_AMOEBA_DRIPPING)
1348 graphic = (element == EL_BD_AMOEBA ? IMG_BD_AMOEBA_PART1 :
1349 element == EL_AMOEBA_WET ? IMG_AMOEBA_WET_PART1 :
1350 element == EL_AMOEBA_DRY ? IMG_AMOEBA_DRY_PART1 :
1351 element == EL_AMOEBA_FULL ? IMG_AMOEBA_FULL_PART1 :
1352 IMG_AMOEBA_DEAD_PART1);
1354 graphic += (x + 2 * y + 4) % 4;
1358 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
1359 else if (mask_mode == USE_MASKING)
1360 DrawGraphicThruMask(x, y, graphic, frame);
1362 DrawGraphic(x, y, graphic, frame);
1365 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1366 int cut_mode, int mask_mode)
1368 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1369 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1370 cut_mode, mask_mode);
1373 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1376 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1379 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1382 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1386 void DrawOldScreenElementThruMask(int x, int y, int element)
1388 DrawOldScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1391 void DrawScreenElementThruMask(int x, int y, int element)
1393 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1397 void DrawLevelElementThruMask(int x, int y, int element)
1399 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1402 void DrawLevelFieldThruMask(int x, int y)
1404 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1407 void DrawCrumbledSand(int x, int y)
1411 int i, width, height, cx,cy;
1412 int ux = LEVELX(x), uy = LEVELY(y);
1413 int element, graphic;
1415 static int xy[4][2] =
1423 if (!IN_LEV_FIELD(ux, uy))
1426 element = Feld[ux][uy];
1428 if (element == EL_SAND ||
1429 element == EL_LANDMINE ||
1430 element == EL_TRAP ||
1431 element == EL_TRAP_ACTIVE)
1433 if (!IN_SCR_FIELD(x, y))
1436 graphic = IMG_SAND_CRUMBLED;
1438 src_bitmap = new_graphic_info[graphic].bitmap;
1439 src_x = new_graphic_info[graphic].src_x;
1440 src_y = new_graphic_info[graphic].src_y;
1446 uxx = ux + xy[i][0];
1447 uyy = uy + xy[i][1];
1448 if (!IN_LEV_FIELD(uxx, uyy))
1449 element = EL_STEELWALL;
1451 element = Feld[uxx][uyy];
1453 if (element == EL_SAND ||
1454 element == EL_LANDMINE ||
1455 element == EL_TRAP ||
1456 element == EL_TRAP_ACTIVE)
1459 if (i == 1 || i == 2)
1463 cx = (i == 2 ? TILEX - snip : 0);
1471 cy = (i == 3 ? TILEY - snip : 0);
1474 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1475 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1478 MarkTileDirty(x, y);
1482 graphic = IMG_SAND_CRUMBLED;
1484 src_bitmap = new_graphic_info[graphic].bitmap;
1485 src_x = new_graphic_info[graphic].src_x;
1486 src_y = new_graphic_info[graphic].src_y;
1490 int xx, yy, uxx, uyy;
1494 uxx = ux + xy[i][0];
1495 uyy = uy + xy[i][1];
1497 if (!IN_LEV_FIELD(uxx, uyy) ||
1498 (Feld[uxx][uyy] != EL_SAND &&
1499 Feld[uxx][uyy] != EL_LANDMINE &&
1500 Feld[uxx][uyy] != EL_TRAP &&
1501 Feld[uxx][uyy] != EL_TRAP_ACTIVE) ||
1502 !IN_SCR_FIELD(xx, yy))
1505 if (i == 1 || i == 2)
1509 cx = (i == 1 ? TILEX - snip : 0);
1517 cy = (i==0 ? TILEY-snip : 0);
1520 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1521 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1523 MarkTileDirty(xx, yy);
1528 void DrawScreenElement(int x, int y, int element)
1530 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1531 DrawCrumbledSand(x, y);
1534 void DrawLevelElement(int x, int y, int element)
1536 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1537 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1540 void DrawScreenField(int x, int y)
1542 int ux = LEVELX(x), uy = LEVELY(y);
1543 int element, content;
1545 if (!IN_LEV_FIELD(ux, uy))
1547 if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
1550 element = BorderElement;
1552 DrawScreenElement(x, y, element);
1556 element = Feld[ux][uy];
1557 content = Store[ux][uy];
1559 if (IS_MOVING(ux, uy))
1561 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1562 boolean cut_mode = NO_CUTTING;
1564 if (element == EL_QUICKSAND_EMPTYING ||
1565 element == EL_MAGIC_WALL_EMPTYING ||
1566 element == EL_BD_MAGIC_WALL_EMPTYING ||
1567 element == EL_AMOEBA_DRIPPING)
1568 cut_mode = CUT_ABOVE;
1569 else if (element == EL_QUICKSAND_FILLING ||
1570 element == EL_MAGIC_WALL_FILLING ||
1571 element == EL_BD_MAGIC_WALL_FILLING)
1572 cut_mode = CUT_BELOW;
1574 if (cut_mode == CUT_ABOVE)
1575 DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1577 DrawScreenElement(x, y, EL_EMPTY);
1580 DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1581 else if (cut_mode == NO_CUTTING)
1582 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1584 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], content, cut_mode);
1586 if (content == EL_ACID)
1587 DrawLevelElementThruMask(ux, uy + 1, EL_ACID);
1589 else if (IS_BLOCKED(ux, uy))
1594 boolean cut_mode = NO_CUTTING;
1595 int element_old, content_old;
1597 Blocked2Moving(ux, uy, &oldx, &oldy);
1600 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1601 MovDir[oldx][oldy] == MV_RIGHT);
1603 element_old = Feld[oldx][oldy];
1604 content_old = Store[oldx][oldy];
1606 if (element_old == EL_QUICKSAND_EMPTYING ||
1607 element_old == EL_MAGIC_WALL_EMPTYING ||
1608 element_old == EL_BD_MAGIC_WALL_EMPTYING ||
1609 element_old == EL_AMOEBA_DRIPPING)
1610 cut_mode = CUT_ABOVE;
1612 DrawScreenElement(x, y, EL_EMPTY);
1615 DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
1617 else if (cut_mode == NO_CUTTING)
1618 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
1621 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
1624 else if (IS_DRAWABLE(element))
1625 DrawScreenElement(x, y, element);
1627 DrawScreenElement(x, y, EL_EMPTY);
1630 void DrawLevelField(int x, int y)
1632 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1633 DrawScreenField(SCREENX(x), SCREENY(y));
1634 else if (IS_MOVING(x, y))
1638 Moving2Blocked(x, y, &newx, &newy);
1639 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1640 DrawScreenField(SCREENX(newx), SCREENY(newy));
1642 else if (IS_BLOCKED(x, y))
1646 Blocked2Moving(x, y, &oldx, &oldy);
1647 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1648 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1652 void DrawMiniElement(int x, int y, int element)
1656 graphic = el2img(element);
1657 DrawMiniGraphic(x, y, graphic);
1660 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1662 int x = sx + scroll_x, y = sy + scroll_y;
1664 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1665 DrawMiniElement(sx, sy, EL_EMPTY);
1666 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1667 DrawMiniElement(sx, sy, Feld[x][y]);
1670 int steel_type, steel_position;
1673 { IMG_STEELWALL_TOPLEFT, IMG_INVISIBLE_STEELWALL_TOPLEFT },
1674 { IMG_STEELWALL_TOPRIGHT, IMG_INVISIBLE_STEELWALL_TOPRIGHT },
1675 { IMG_STEELWALL_BOTTOMLEFT, IMG_INVISIBLE_STEELWALL_BOTTOMLEFT },
1676 { IMG_STEELWALL_BOTTOMRIGHT, IMG_INVISIBLE_STEELWALL_BOTTOMRIGHT },
1677 { IMG_STEELWALL_VERTICAL, IMG_INVISIBLE_STEELWALL_VERTICAL },
1678 { IMG_STEELWALL_HORIZONTAL, IMG_INVISIBLE_STEELWALL_HORIZONTAL }
1681 steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
1682 steel_position = (x == -1 && y == -1 ? 0 :
1683 x == lev_fieldx && y == -1 ? 1 :
1684 x == -1 && y == lev_fieldy ? 2 :
1685 x == lev_fieldx && y == lev_fieldy ? 3 :
1686 x == -1 || x == lev_fieldx ? 4 :
1687 y == -1 || y == lev_fieldy ? 5 : -1);
1689 if (steel_position != -1)
1690 DrawMiniGraphic(sx, sy, border[steel_position][steel_type]);
1694 void getMicroGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1696 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
1697 int mini_startx = src_bitmap->width * 3 / 4;
1698 int mini_starty = src_bitmap->height * 2 / 3;
1699 int src_x = mini_startx + new_graphic_info[graphic].src_x / 8;
1700 int src_y = mini_starty + new_graphic_info[graphic].src_y / 8;
1702 *bitmap = src_bitmap;
1707 void DrawMicroElement(int xpos, int ypos, int element)
1713 if (element == EL_EMPTY)
1716 graphic = el2img(element);
1718 getMicroGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1719 BlitBitmap(src_bitmap, drawto, src_x, src_y, MICRO_TILEX, MICRO_TILEY,
1729 for(x=BX1; x<=BX2; x++)
1730 for(y=BY1; y<=BY2; y++)
1731 DrawScreenField(x, y);
1733 redraw_mask |= REDRAW_FIELD;
1736 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1740 for(x=0; x<size_x; x++)
1741 for(y=0; y<size_y; y++)
1742 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1744 redraw_mask |= REDRAW_FIELD;
1747 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1751 ClearRectangle(drawto, xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
1753 if (lev_fieldx < STD_LEV_FIELDX)
1754 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1755 if (lev_fieldy < STD_LEV_FIELDY)
1756 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1758 xpos += MICRO_TILEX;
1759 ypos += MICRO_TILEY;
1761 for(x=-1; x<=STD_LEV_FIELDX; x++)
1763 for(y=-1; y<=STD_LEV_FIELDY; y++)
1765 int lx = from_x + x, ly = from_y + y;
1767 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1768 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1770 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1)
1771 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1776 redraw_mask |= REDRAW_MICROLEVEL;
1779 #define MICROLABEL_EMPTY 0
1780 #define MICROLABEL_LEVEL_NAME 1
1781 #define MICROLABEL_CREATED_BY 2
1782 #define MICROLABEL_LEVEL_AUTHOR 3
1783 #define MICROLABEL_IMPORTED_FROM 4
1784 #define MICROLABEL_LEVEL_IMPORT_INFO 5
1786 #define MAX_MICROLABEL_SIZE (SXSIZE / FONT4_XSIZE)
1788 static void DrawMicroLevelLabelExt(int mode)
1790 char label_text[MAX_MICROLABEL_SIZE + 1];
1792 ClearRectangle(drawto, SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
1794 strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
1795 mode == MICROLABEL_CREATED_BY ? "created by" :
1796 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
1797 mode == MICROLABEL_IMPORTED_FROM ? "imported from" :
1798 mode == MICROLABEL_LEVEL_IMPORT_INFO ?
1799 leveldir_current->imported_from : ""),
1800 MAX_MICROLABEL_SIZE);
1801 label_text[MAX_MICROLABEL_SIZE] = '\0';
1803 if (strlen(label_text) > 0)
1805 int lxpos = SX + (SXSIZE - strlen(label_text) * FONT4_XSIZE) / 2;
1806 int lypos = MICROLABEL_YPOS;
1808 DrawText(lxpos, lypos, label_text, FS_SMALL, FC_SPECIAL2);
1811 redraw_mask |= REDRAW_MICROLEVEL;
1814 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1816 static unsigned long scroll_delay = 0;
1817 static unsigned long label_delay = 0;
1818 static int from_x, from_y, scroll_direction;
1819 static int label_state, label_counter;
1823 from_x = from_y = 0;
1824 scroll_direction = MV_RIGHT;
1828 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1829 DrawMicroLevelLabelExt(label_state);
1831 /* initialize delay counters */
1832 DelayReached(&scroll_delay, 0);
1833 DelayReached(&label_delay, 0);
1838 /* scroll micro level, if needed */
1839 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1840 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1842 switch (scroll_direction)
1848 scroll_direction = MV_UP;
1852 if (from_x < lev_fieldx - STD_LEV_FIELDX)
1855 scroll_direction = MV_DOWN;
1862 scroll_direction = MV_RIGHT;
1866 if (from_y < lev_fieldy - STD_LEV_FIELDY)
1869 scroll_direction = MV_LEFT;
1876 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1879 /* redraw micro level label, if needed */
1880 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1881 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1882 strcmp(level.author, leveldir_current->name) != 0 &&
1883 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1885 int max_label_counter = 23;
1887 if (leveldir_current->imported_from != NULL)
1888 max_label_counter += 14;
1890 label_counter = (label_counter + 1) % max_label_counter;
1891 label_state = (label_counter >= 0 && label_counter <= 7 ?
1892 MICROLABEL_LEVEL_NAME :
1893 label_counter >= 9 && label_counter <= 12 ?
1894 MICROLABEL_CREATED_BY :
1895 label_counter >= 14 && label_counter <= 21 ?
1896 MICROLABEL_LEVEL_AUTHOR :
1897 label_counter >= 23 && label_counter <= 26 ?
1898 MICROLABEL_IMPORTED_FROM :
1899 label_counter >= 28 && label_counter <= 35 ?
1900 MICROLABEL_LEVEL_IMPORT_INFO : MICROLABEL_EMPTY);
1901 DrawMicroLevelLabelExt(label_state);
1905 int REQ_in_range(int x, int y)
1907 if (y > DY+249 && y < DY+278)
1909 if (x > DX+1 && x < DX+48)
1911 else if (x > DX+51 && x < DX+98)
1917 #define MAX_REQUEST_LINES 13
1918 #define MAX_REQUEST_LINE_LEN 7
1920 boolean Request(char *text, unsigned int req_state)
1922 int mx, my, ty, result = -1;
1923 unsigned int old_door_state;
1925 #if defined(PLATFORM_UNIX)
1926 /* pause network game while waiting for request to answer */
1927 if (options.network &&
1928 game_status == PLAYING &&
1929 req_state & REQUEST_WAIT_FOR)
1930 SendToServer_PausePlaying();
1933 old_door_state = GetDoorState();
1937 CloseDoor(DOOR_CLOSE_1);
1939 /* save old door content */
1940 BlitBitmap(pix[PIX_DB_DOOR], pix[PIX_DB_DOOR],
1941 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
1942 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
1944 /* clear door drawing field */
1945 ClearRectangle(drawto, DX, DY, DXSIZE, DYSIZE);
1947 /* write text for request */
1948 for(ty=0; ty < MAX_REQUEST_LINES; ty++)
1950 char text_line[MAX_REQUEST_LINE_LEN + 1];
1956 for(tl=0,tx=0; tx < MAX_REQUEST_LINE_LEN; tl++,tx++)
1959 if (!tc || tc == ' ')
1970 strncpy(text_line, text, tl);
1973 DrawTextExt(drawto, DX + 50 - (tl * 14)/2, DY + 8 + ty * 16,
1974 text_line, FS_SMALL, FC_YELLOW);
1976 text += tl + (tc == ' ' ? 1 : 0);
1979 if (req_state & REQ_ASK)
1981 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
1982 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
1984 else if (req_state & REQ_CONFIRM)
1986 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
1988 else if (req_state & REQ_PLAYER)
1990 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
1991 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
1992 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
1993 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
1996 /* copy request gadgets to door backbuffer */
1997 BlitBitmap(drawto, pix[PIX_DB_DOOR],
1998 DX, DY, DXSIZE, DYSIZE,
1999 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2001 OpenDoor(DOOR_OPEN_1);
2007 if (!(req_state & REQUEST_WAIT_FOR))
2010 if (game_status != MAINMENU)
2013 button_status = MB_RELEASED;
2015 request_gadget_id = -1;
2027 case EVENT_BUTTONPRESS:
2028 case EVENT_BUTTONRELEASE:
2029 case EVENT_MOTIONNOTIFY:
2031 if (event.type == EVENT_MOTIONNOTIFY)
2033 if (!PointerInWindow(window))
2034 continue; /* window and pointer are on different screens */
2039 motion_status = TRUE;
2040 mx = ((MotionEvent *) &event)->x;
2041 my = ((MotionEvent *) &event)->y;
2045 motion_status = FALSE;
2046 mx = ((ButtonEvent *) &event)->x;
2047 my = ((ButtonEvent *) &event)->y;
2048 if (event.type == EVENT_BUTTONPRESS)
2049 button_status = ((ButtonEvent *) &event)->button;
2051 button_status = MB_RELEASED;
2054 /* this sets 'request_gadget_id' */
2055 HandleGadgets(mx, my, button_status);
2057 switch(request_gadget_id)
2059 case TOOL_CTRL_ID_YES:
2062 case TOOL_CTRL_ID_NO:
2065 case TOOL_CTRL_ID_CONFIRM:
2066 result = TRUE | FALSE;
2069 case TOOL_CTRL_ID_PLAYER_1:
2072 case TOOL_CTRL_ID_PLAYER_2:
2075 case TOOL_CTRL_ID_PLAYER_3:
2078 case TOOL_CTRL_ID_PLAYER_4:
2089 case EVENT_KEYPRESS:
2090 switch(GetEventKey((KeyEvent *)&event, TRUE))
2103 if (req_state & REQ_PLAYER)
2107 case EVENT_KEYRELEASE:
2108 ClearPlayerAction();
2112 HandleOtherEvents(&event);
2116 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2118 int joy = AnyJoystick();
2120 if (joy & JOY_BUTTON_1)
2122 else if (joy & JOY_BUTTON_2)
2128 /* don't eat all CPU time */
2132 if (game_status != MAINMENU)
2137 if (!(req_state & REQ_STAY_OPEN))
2139 CloseDoor(DOOR_CLOSE_1);
2141 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
2143 BlitBitmap(pix[PIX_DB_DOOR], pix[PIX_DB_DOOR],
2144 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
2145 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
2146 OpenDoor(DOOR_OPEN_1);
2152 #if defined(PLATFORM_UNIX)
2153 /* continue network game after request */
2154 if (options.network &&
2155 game_status == PLAYING &&
2156 req_state & REQUEST_WAIT_FOR)
2157 SendToServer_ContinuePlaying();
2163 unsigned int OpenDoor(unsigned int door_state)
2165 unsigned int new_door_state;
2167 if (door_state & DOOR_COPY_BACK)
2169 BlitBitmap(pix[PIX_DB_DOOR], pix[PIX_DB_DOOR],
2170 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
2171 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2172 door_state &= ~DOOR_COPY_BACK;
2175 new_door_state = MoveDoor(door_state);
2177 return(new_door_state);
2180 unsigned int CloseDoor(unsigned int door_state)
2182 unsigned int new_door_state;
2184 BlitBitmap(backbuffer, pix[PIX_DB_DOOR],
2185 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2186 BlitBitmap(backbuffer, pix[PIX_DB_DOOR],
2187 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2189 new_door_state = MoveDoor(door_state);
2191 return(new_door_state);
2194 unsigned int GetDoorState()
2196 return MoveDoor(DOOR_GET_STATE);
2199 unsigned int SetDoorState(unsigned int door_state)
2201 return MoveDoor(door_state | DOOR_SET_STATE);
2204 unsigned int MoveDoor(unsigned int door_state)
2206 static int door1 = DOOR_OPEN_1;
2207 static int door2 = DOOR_CLOSE_2;
2208 static unsigned long door_delay = 0;
2209 int x, start, stepsize = 2;
2210 unsigned long door_delay_value = stepsize * 5;
2212 if (door_state == DOOR_GET_STATE)
2213 return(door1 | door2);
2215 if (door_state & DOOR_SET_STATE)
2217 if (door_state & DOOR_ACTION_1)
2218 door1 = door_state & DOOR_ACTION_1;
2219 if (door_state & DOOR_ACTION_2)
2220 door2 = door_state & DOOR_ACTION_2;
2222 return(door1 | door2);
2225 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2226 door_state &= ~DOOR_OPEN_1;
2227 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2228 door_state &= ~DOOR_CLOSE_1;
2229 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2230 door_state &= ~DOOR_OPEN_2;
2231 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2232 door_state &= ~DOOR_CLOSE_2;
2234 if (setup.quick_doors)
2237 door_delay_value = 0;
2238 StopSound(SND_MENU_DOOR_OPENING);
2239 StopSound(SND_MENU_DOOR_CLOSING);
2242 if (door_state & DOOR_ACTION)
2244 if (!(door_state & DOOR_NO_DELAY))
2246 /* opening door sound has priority over simultaneously closing door */
2247 if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
2248 PlaySoundStereo(SND_MENU_DOOR_OPENING, SOUND_MAX_RIGHT);
2249 else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
2250 PlaySoundStereo(SND_MENU_DOOR_CLOSING, SOUND_MAX_RIGHT);
2253 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2255 for(x=start; x<=DXSIZE; x+=stepsize)
2257 Bitmap *bitmap = pix[PIX_DOOR];
2258 GC gc = bitmap->stored_clip_gc;
2260 WaitUntilDelayReached(&door_delay, door_delay_value);
2262 if (door_state & DOOR_ACTION_1)
2264 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
2265 int j = (DXSIZE - i) / 3;
2267 BlitBitmap(pix[PIX_DB_DOOR], drawto,
2268 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
2269 DXSIZE,DYSIZE - i/2, DX, DY);
2271 ClearRectangle(drawto, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
2273 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2274 BlitBitmapMasked(bitmap, drawto,
2275 DXSIZE, DOOR_GFX_PAGEY1, i, 77,
2276 DX + DXSIZE - i, DY + j);
2277 BlitBitmapMasked(bitmap, drawto,
2278 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
2279 DX + DXSIZE - i, DY + 140 + j);
2280 SetClipOrigin(bitmap, gc, DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
2281 BlitBitmapMasked(bitmap, drawto,
2282 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
2284 BlitBitmapMasked(bitmap, drawto,
2285 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
2288 BlitBitmapMasked(bitmap, drawto,
2289 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2291 BlitBitmapMasked(bitmap, drawto,
2292 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2294 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2295 BlitBitmapMasked(bitmap, drawto,
2296 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2297 DX + DXSIZE - i, DY + 77 + j);
2298 BlitBitmapMasked(bitmap, drawto,
2299 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2300 DX + DXSIZE - i, DY + 203 + j);
2302 redraw_mask |= REDRAW_DOOR_1;
2305 if (door_state & DOOR_ACTION_2)
2307 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
2308 int j = (VXSIZE - i) / 3;
2310 BlitBitmap(pix[PIX_DB_DOOR], drawto,
2311 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
2312 VXSIZE, VYSIZE - i/2, VX, VY);
2314 ClearRectangle(drawto, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
2316 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2317 BlitBitmapMasked(bitmap, drawto,
2318 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
2319 VX + VXSIZE-i, VY+j);
2320 SetClipOrigin(bitmap, gc,
2321 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2322 BlitBitmapMasked(bitmap, drawto,
2323 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
2326 BlitBitmapMasked(bitmap, drawto,
2327 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2328 i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
2329 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2330 BlitBitmapMasked(bitmap, drawto,
2331 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2333 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2335 redraw_mask |= REDRAW_DOOR_2;
2340 if (game_status == MAINMENU)
2345 if (setup.quick_doors)
2347 StopSound(SND_MENU_DOOR_OPENING);
2348 StopSound(SND_MENU_DOOR_CLOSING);
2351 if (door_state & DOOR_ACTION_1)
2352 door1 = door_state & DOOR_ACTION_1;
2353 if (door_state & DOOR_ACTION_2)
2354 door2 = door_state & DOOR_ACTION_2;
2356 return (door1 | door2);
2359 void DrawSpecialEditorDoor()
2361 /* draw bigger toolbox window */
2362 BlitBitmap(pix[PIX_DOOR], drawto,
2363 DOOR_GFX_PAGEX7, 0, 108, 56, EX - 4, EY - 12);
2365 redraw_mask |= REDRAW_ALL;
2368 void UndrawSpecialEditorDoor()
2370 /* draw normal tape recorder window */
2371 BlitBitmap(pix[PIX_BACK], drawto,
2372 562, 344, 108, 56, EX - 4, EY - 12);
2374 redraw_mask |= REDRAW_ALL;
2378 int ReadPixel(DrawBuffer *bitmap, int x, int y)
2380 XImage *pixel_image;
2381 unsigned long pixel_value;
2383 pixel_image = XGetImage(display, bitmap->drawable,
2384 x, y, 1, 1, AllPlanes, ZPixmap);
2385 pixel_value = XGetPixel(pixel_image, 0, 0);
2387 XDestroyImage(pixel_image);
2393 /* ---------- new tool button stuff ---------------------------------------- */
2395 /* graphic position values for tool buttons */
2396 #define TOOL_BUTTON_YES_XPOS 2
2397 #define TOOL_BUTTON_YES_YPOS 250
2398 #define TOOL_BUTTON_YES_GFX_YPOS 0
2399 #define TOOL_BUTTON_YES_XSIZE 46
2400 #define TOOL_BUTTON_YES_YSIZE 28
2401 #define TOOL_BUTTON_NO_XPOS 52
2402 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2403 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2404 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2405 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2406 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2407 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2408 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2409 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2410 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2411 #define TOOL_BUTTON_PLAYER_XSIZE 30
2412 #define TOOL_BUTTON_PLAYER_YSIZE 30
2413 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2414 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2415 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2416 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2417 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2418 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2419 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2420 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2421 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2422 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2423 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2424 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2425 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2426 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2427 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2428 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2429 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2430 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2431 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2432 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2441 } toolbutton_info[NUM_TOOL_BUTTONS] =
2444 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2445 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2446 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2451 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2452 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2453 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2458 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2459 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2460 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2461 TOOL_CTRL_ID_CONFIRM,
2465 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2466 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2467 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2468 TOOL_CTRL_ID_PLAYER_1,
2472 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2473 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2474 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2475 TOOL_CTRL_ID_PLAYER_2,
2479 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2480 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2481 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2482 TOOL_CTRL_ID_PLAYER_3,
2486 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2487 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2488 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2489 TOOL_CTRL_ID_PLAYER_4,
2494 void CreateToolButtons()
2498 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2500 Bitmap *gd_bitmap = pix[PIX_DOOR];
2501 Bitmap *deco_bitmap = None;
2502 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2503 struct GadgetInfo *gi;
2504 unsigned long event_mask;
2505 int gd_xoffset, gd_yoffset;
2506 int gd_x1, gd_x2, gd_y;
2509 event_mask = GD_EVENT_RELEASED;
2511 gd_xoffset = toolbutton_info[i].xpos;
2512 gd_yoffset = toolbutton_info[i].ypos;
2513 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2514 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2515 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2517 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2519 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
2521 getMiniGraphicSource(PLAYER_NR_GFX(IMG_PLAYER1, player_nr),
2522 &deco_bitmap, &deco_x, &deco_y);
2523 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2524 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2527 gi = CreateGadget(GDI_CUSTOM_ID, id,
2528 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2529 GDI_X, DX + toolbutton_info[i].x,
2530 GDI_Y, DY + toolbutton_info[i].y,
2531 GDI_WIDTH, toolbutton_info[i].width,
2532 GDI_HEIGHT, toolbutton_info[i].height,
2533 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2534 GDI_STATE, GD_BUTTON_UNPRESSED,
2535 GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
2536 GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
2537 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
2538 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2539 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2540 GDI_DECORATION_SHIFTING, 1, 1,
2541 GDI_EVENT_MASK, event_mask,
2542 GDI_CALLBACK_ACTION, HandleToolButtons,
2546 Error(ERR_EXIT, "cannot create gadget");
2548 tool_gadget[id] = gi;
2552 static void UnmapToolButtons()
2556 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2557 UnmapGadget(tool_gadget[i]);
2560 static void HandleToolButtons(struct GadgetInfo *gi)
2562 request_gadget_id = gi->custom_id;
2565 int get_next_element(int element)
2569 case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL;
2570 case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY;
2571 case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL;
2572 case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_ACTIVE;
2573 case EL_BD_MAGIC_WALL_FILLING: return EL_BD_MAGIC_WALL_FULL;
2574 case EL_BD_MAGIC_WALL_EMPTYING: return EL_BD_MAGIC_WALL_ACTIVE;
2575 case EL_AMOEBA_DRIPPING: return EL_AMOEBA_WET;
2577 default: return element;
2581 int el2gfx_OLD(int element)
2585 case EL_EMPTY: return -1;
2586 case EL_SAND: return GFX_ERDREICH;
2587 case EL_WALL: return GFX_MAUERWERK;
2588 case EL_WALL_CRUMBLED: return GFX_FELSBODEN;
2589 case EL_ROCK: return GFX_FELSBROCKEN;
2590 case EL_EMERALD: return GFX_EDELSTEIN;
2591 case EL_EXIT_CLOSED: return GFX_AUSGANG_ZU;
2592 case EL_EXIT_OPENING: return GFX_AUSGANG_ACT;
2593 case EL_EXIT_OPEN: return GFX_AUSGANG_AUF;
2594 case EL_SP_EXIT_OPEN: return GFX_SP_EXIT;
2595 case EL_PLAYER1: return GFX_SPIELER1;
2596 case EL_PLAYER2: return GFX_SPIELER2;
2597 case EL_PLAYER3: return GFX_SPIELER3;
2598 case EL_PLAYER4: return GFX_SPIELER4;
2599 case EL_BUG: return GFX_KAEFER;
2600 case EL_BUG_RIGHT: return GFX_KAEFER_RIGHT;
2601 case EL_BUG_UP: return GFX_KAEFER_UP;
2602 case EL_BUG_LEFT: return GFX_KAEFER_LEFT;
2603 case EL_BUG_DOWN: return GFX_KAEFER_DOWN;
2604 case EL_SPACESHIP: return GFX_FLIEGER;
2605 case EL_SPACESHIP_RIGHT: return GFX_FLIEGER_RIGHT;
2606 case EL_SPACESHIP_UP: return GFX_FLIEGER_UP;
2607 case EL_SPACESHIP_LEFT: return GFX_FLIEGER_LEFT;
2608 case EL_SPACESHIP_DOWN: return GFX_FLIEGER_DOWN;
2609 case EL_BD_BUTTERFLY: return GFX_BUTTERFLY;
2610 case EL_BD_BUTTERFLY_RIGHT: return GFX_BUTTERFLY_RIGHT;
2611 case EL_BD_BUTTERFLY_UP: return GFX_BUTTERFLY_UP;
2612 case EL_BD_BUTTERFLY_LEFT: return GFX_BUTTERFLY_LEFT;
2613 case EL_BD_BUTTERFLY_DOWN: return GFX_BUTTERFLY_DOWN;
2614 case EL_BD_FIREFLY: return GFX_FIREFLY;
2615 case EL_BD_FIREFLY_RIGHT: return GFX_FIREFLY_RIGHT;
2616 case EL_BD_FIREFLY_UP: return GFX_FIREFLY_UP;
2617 case EL_BD_FIREFLY_LEFT: return GFX_FIREFLY_LEFT;
2618 case EL_BD_FIREFLY_DOWN: return GFX_FIREFLY_DOWN;
2619 case EL_YAMYAM: return GFX_MAMPFER;
2620 case EL_ROBOT: return GFX_ROBOT;
2621 case EL_STEELWALL: return GFX_BETON;
2622 case EL_DIAMOND: return GFX_DIAMANT;
2623 case EL_QUICKSAND_EMPTY: return GFX_MORAST_LEER;
2624 case EL_QUICKSAND_FULL: return GFX_MORAST_VOLL;
2625 case EL_QUICKSAND_EMPTYING: return GFX_MORAST_LEER;
2626 case EL_AMOEBA_DROP: return GFX_TROPFEN;
2627 case EL_BOMB: return GFX_BOMBE;
2628 case EL_MAGIC_WALL: return GFX_MAGIC_WALL_OFF;
2629 case EL_MAGIC_WALL_ACTIVE: return GFX_MAGIC_WALL_EMPTY;
2630 case EL_MAGIC_WALL_EMPTYING: return GFX_MAGIC_WALL_EMPTY;
2631 case EL_MAGIC_WALL_FULL: return GFX_MAGIC_WALL_FULL;
2632 case EL_MAGIC_WALL_DEAD: return GFX_MAGIC_WALL_DEAD;
2633 case EL_ACID: return GFX_SALZSAEURE;
2634 case EL_AMOEBA_DEAD: return GFX_AMOEBE_TOT;
2635 case EL_AMOEBA_WET: return GFX_AMOEBE_NASS;
2636 case EL_AMOEBA_DRY: return GFX_AMOEBE_NORM;
2637 case EL_AMOEBA_FULL: return GFX_AMOEBE_VOLL;
2638 case EL_BD_AMOEBA: return GFX_AMOEBE_BD;
2639 case EL_AMOEBA_TO_DIAMOND: return GFX_AMOEBA2DIAM;
2640 case EL_AMOEBA_DRIPPING: return GFX_AMOEBE_NASS;
2641 case EL_NUT: return GFX_KOKOSNUSS;
2642 case EL_GAMEOFLIFE: return GFX_LIFE;
2643 case EL_BIOMAZE: return GFX_LIFE_ASYNC;
2644 case EL_DYNAMITE_ACTIVE: return GFX_DYNAMIT;
2645 case EL_STONEBLOCK: return GFX_BADEWANNE;
2646 case EL_ACIDPOOL_TOPLEFT: return GFX_BADEWANNE1;
2647 case EL_ACIDPOOL_TOPRIGHT: return GFX_BADEWANNE2;
2648 case EL_ACIDPOOL_BOTTOMLEFT: return GFX_BADEWANNE3;
2649 case EL_ACIDPOOL_BOTTOM: return GFX_BADEWANNE4;
2650 case EL_ACIDPOOL_BOTTOMRIGHT: return GFX_BADEWANNE5;
2651 case EL_ROBOT_WHEEL: return GFX_ABLENK_AUS;
2652 case EL_ROBOT_WHEEL_ACTIVE: return GFX_ABLENK_EIN;
2653 case EL_KEY1: return GFX_SCHLUESSEL1;
2654 case EL_KEY2: return GFX_SCHLUESSEL2;
2655 case EL_KEY3: return GFX_SCHLUESSEL3;
2656 case EL_KEY4: return GFX_SCHLUESSEL4;
2657 case EL_GATE1: return GFX_PFORTE1;
2658 case EL_GATE2: return GFX_PFORTE2;
2659 case EL_GATE3: return GFX_PFORTE3;
2660 case EL_GATE4: return GFX_PFORTE4;
2661 case EL_GATE1_GRAY: return GFX_PFORTE1X;
2662 case EL_GATE2_GRAY: return GFX_PFORTE2X;
2663 case EL_GATE3_GRAY: return GFX_PFORTE3X;
2664 case EL_GATE4_GRAY: return GFX_PFORTE4X;
2665 case EL_DYNAMITE: return GFX_DYNAMIT_AUS;
2666 case EL_PACMAN: return GFX_PACMAN;
2667 case EL_PACMAN_RIGHT: return GFX_PACMAN_RIGHT;
2668 case EL_PACMAN_UP: return GFX_PACMAN_UP;
2669 case EL_PACMAN_LEFT: return GFX_PACMAN_LEFT;
2670 case EL_PACMAN_DOWN: return GFX_PACMAN_DOWN;
2671 case EL_INVISIBLE_WALL: return GFX_UNSICHTBAR;
2672 case EL_INVISIBLE_WALL_ACTIVE: return GFX_UNSICHTBAR_ON;
2673 case EL_WALL_EMERALD: return GFX_ERZ_EDEL;
2674 case EL_WALL_DIAMOND: return GFX_ERZ_DIAM;
2675 case EL_LAMP: return GFX_BIRNE_AUS;
2676 case EL_LAMP_ACTIVE: return GFX_BIRNE_EIN;
2677 case EL_TIME_ORB_FULL: return GFX_ZEIT_VOLL;
2678 case EL_TIME_ORB_EMPTY: return GFX_ZEIT_LEER;
2679 case EL_WALL_GROWING: return GFX_MAUER_LEBT;
2680 case EL_WALL_GROWING_X: return GFX_MAUER_X;
2681 case EL_WALL_GROWING_Y: return GFX_MAUER_Y;
2682 case EL_WALL_GROWING_XY: return GFX_MAUER_XY;
2683 case EL_BD_DIAMOND: return GFX_EDELSTEIN_BD;
2684 case EL_EMERALD_YELLOW: return GFX_EDELSTEIN_GELB;
2685 case EL_EMERALD_RED: return GFX_EDELSTEIN_ROT;
2686 case EL_EMERALD_PURPLE: return GFX_EDELSTEIN_LILA;
2687 case EL_WALL_BD_DIAMOND: return GFX_ERZ_EDEL_BD;
2688 case EL_WALL_EMERALD_YELLOW: return GFX_ERZ_EDEL_GELB;
2689 case EL_WALL_EMERALD_RED: return GFX_ERZ_EDEL_ROT;
2690 case EL_WALL_EMERALD_PURPLE: return GFX_ERZ_EDEL_LILA;
2691 case EL_DARK_YAMYAM: return GFX_MAMPFER2;
2692 case EL_BD_MAGIC_WALL: return GFX_MAGIC_WALL_BD_OFF;
2693 case EL_BD_MAGIC_WALL_ACTIVE: return GFX_MAGIC_WALL_BD_EMPTY;
2694 case EL_BD_MAGIC_WALL_EMPTYING: return GFX_MAGIC_WALL_BD_EMPTY;
2695 case EL_BD_MAGIC_WALL_FULL: return GFX_MAGIC_WALL_BD_FULL;
2696 case EL_BD_MAGIC_WALL_DEAD: return GFX_MAGIC_WALL_BD_DEAD;
2697 case EL_DYNABOMB_PLAYER1_ACTIVE: return GFX_DYNABOMB;
2698 case EL_DYNABOMB_PLAYER2_ACTIVE: return GFX_DYNABOMB;
2699 case EL_DYNABOMB_PLAYER3_ACTIVE: return GFX_DYNABOMB;
2700 case EL_DYNABOMB_PLAYER4_ACTIVE: return GFX_DYNABOMB;
2701 case EL_DYNABOMB_NR: return GFX_DYNABOMB_NR;
2702 case EL_DYNABOMB_SZ: return GFX_DYNABOMB_SZ;
2703 case EL_DYNABOMB_XL: return GFX_DYNABOMB_XL;
2704 case EL_SOKOBAN_OBJECT: return GFX_SOKOBAN_OBJEKT;
2705 case EL_SOKOBAN_FIELD_EMPTY: return GFX_SOKOBAN_FELD_LEER;
2706 case EL_SOKOBAN_FIELD_FULL: return GFX_SOKOBAN_FELD_VOLL;
2707 case EL_MOLE: return GFX_MOLE;
2708 case EL_PENGUIN: return GFX_PINGUIN;
2709 case EL_PIG: return GFX_SCHWEIN;
2710 case EL_DRAGON: return GFX_DRACHE;
2711 case EL_SATELLITE: return GFX_SONDE;
2712 case EL_ARROW_BLUE_LEFT: return GFX_PFEIL_LEFT;
2713 case EL_ARROW_BLUE_RIGHT: return GFX_PFEIL_RIGHT;
2714 case EL_ARROW_BLUE_UP: return GFX_PFEIL_UP;
2715 case EL_ARROW_BLUE_DOWN: return GFX_PFEIL_DOWN;
2716 case EL_SPEED_PILL: return GFX_SPEED_PILL;
2717 case EL_SP_TERMINAL_ACTIVE: return GFX_SP_TERMINAL;
2718 case EL_SP_BUGGY_BASE_ACTIVE: return GFX_SP_BUG_ACTIVE;
2719 case EL_SP_ZONK: return GFX_SP_ZONK;
2720 /* ^^^^^^^^^^ non-standard position in supaplex graphic set! */
2721 case EL_INVISIBLE_STEELWALL: return GFX_INVISIBLE_STEEL;
2722 case EL_INVISIBLE_STEELWALL_ACTIVE: return GFX_INVISIBLE_STEEL_ON;
2723 case EL_BLACK_ORB: return GFX_BLACK_ORB;
2724 case EL_EM_GATE1: return GFX_EM_GATE_1;
2725 case EL_EM_GATE2: return GFX_EM_GATE_2;
2726 case EL_EM_GATE3: return GFX_EM_GATE_3;
2727 case EL_EM_GATE4: return GFX_EM_GATE_4;
2728 case EL_EM_GATE1_GRAY: return GFX_EM_GATE_1X;
2729 case EL_EM_GATE2_GRAY: return GFX_EM_GATE_2X;
2730 case EL_EM_GATE3_GRAY: return GFX_EM_GATE_3X;
2731 case EL_EM_GATE4_GRAY: return GFX_EM_GATE_4X;
2732 case EL_EM_KEY1_FILE: return GFX_EM_KEY_1;
2733 case EL_EM_KEY2_FILE: return GFX_EM_KEY_2;
2734 case EL_EM_KEY3_FILE: return GFX_EM_KEY_3;
2735 case EL_EM_KEY4_FILE: return GFX_EM_KEY_4;
2736 case EL_EM_KEY1: return GFX_EM_KEY_1;
2737 case EL_EM_KEY2: return GFX_EM_KEY_2;
2738 case EL_EM_KEY3: return GFX_EM_KEY_3;
2739 case EL_EM_KEY4: return GFX_EM_KEY_4;
2740 case EL_PEARL: return GFX_PEARL;
2741 case EL_CRYSTAL: return GFX_CRYSTAL;
2742 case EL_WALL_PEARL: return GFX_WALL_PEARL;
2743 case EL_WALL_CRYSTAL: return GFX_WALL_CRYSTAL;
2744 case EL_DOOR_WHITE: return GFX_DOOR_WHITE;
2745 case EL_DOOR_WHITE_GRAY: return GFX_DOOR_WHITE_GRAY;
2746 case EL_KEY_WHITE: return GFX_KEY_WHITE;
2747 case EL_SHIELD_NORMAL: return GFX_SHIELD_PASSIVE;
2748 case EL_SHIELD_DEADLY: return GFX_SHIELD_ACTIVE;
2749 case EL_EXTRA_TIME: return GFX_EXTRA_TIME;
2750 case EL_SWITCHGATE_OPEN: return GFX_SWITCHGATE_OPEN;
2751 case EL_SWITCHGATE_CLOSED: return GFX_SWITCHGATE_CLOSED;
2752 case EL_SWITCHGATE_SWITCH_UP: return GFX_SWITCHGATE_SWITCH_1;
2753 case EL_SWITCHGATE_SWITCH_DOWN: return GFX_SWITCHGATE_SWITCH_2;
2754 case EL_CONVEYOR_BELT1_LEFT: return GFX_BELT1_LEFT;
2755 case EL_CONVEYOR_BELT1_MIDDLE: return GFX_BELT1_MIDDLE;
2756 case EL_CONVEYOR_BELT1_RIGHT: return GFX_BELT1_RIGHT;
2757 case EL_CONVEYOR_BELT1_LEFT_ACTIVE: return GFX_BELT1_LEFT;
2758 case EL_CONVEYOR_BELT1_MIDDLE_ACTIVE:return GFX_BELT1_MIDDLE;
2759 case EL_CONVEYOR_BELT1_RIGHT_ACTIVE:return GFX_BELT1_RIGHT;
2760 case EL_CONVEYOR_BELT1_SWITCH_LEFT: return GFX_BELT1_SWITCH_LEFT;
2761 case EL_CONVEYOR_BELT1_SWITCH_MIDDLE:return GFX_BELT1_SWITCH_MIDDLE;
2762 case EL_CONVEYOR_BELT1_SWITCH_RIGHT:return GFX_BELT1_SWITCH_RIGHT;
2763 case EL_CONVEYOR_BELT2_LEFT: return GFX_BELT2_LEFT;
2764 case EL_CONVEYOR_BELT2_MIDDLE: return GFX_BELT2_MIDDLE;
2765 case EL_CONVEYOR_BELT2_RIGHT: return GFX_BELT2_RIGHT;
2766 case EL_CONVEYOR_BELT2_LEFT_ACTIVE: return GFX_BELT2_LEFT;
2767 case EL_CONVEYOR_BELT2_MIDDLE_ACTIVE:return GFX_BELT2_MIDDLE;
2768 case EL_CONVEYOR_BELT2_RIGHT_ACTIVE:return GFX_BELT2_RIGHT;
2769 case EL_CONVEYOR_BELT2_SWITCH_LEFT: return GFX_BELT2_SWITCH_LEFT;
2770 case EL_CONVEYOR_BELT2_SWITCH_MIDDLE:return GFX_BELT2_SWITCH_MIDDLE;
2771 case EL_CONVEYOR_BELT2_SWITCH_RIGHT:return GFX_BELT2_SWITCH_RIGHT;
2772 case EL_CONVEYOR_BELT3_LEFT: return GFX_BELT3_LEFT;
2773 case EL_CONVEYOR_BELT3_MIDDLE: return GFX_BELT3_MIDDLE;
2774 case EL_CONVEYOR_BELT3_RIGHT: return GFX_BELT3_RIGHT;
2775 case EL_CONVEYOR_BELT3_LEFT_ACTIVE: return GFX_BELT3_LEFT;
2776 case EL_CONVEYOR_BELT3_MIDDLE_ACTIVE:return GFX_BELT3_MIDDLE;
2777 case EL_CONVEYOR_BELT3_RIGHT_ACTIVE:return GFX_BELT3_RIGHT;
2778 case EL_CONVEYOR_BELT3_SWITCH_LEFT: return GFX_BELT3_SWITCH_LEFT;
2779 case EL_CONVEYOR_BELT3_SWITCH_MIDDLE:return GFX_BELT3_SWITCH_MIDDLE;
2780 case EL_CONVEYOR_BELT3_SWITCH_RIGHT:return GFX_BELT3_SWITCH_RIGHT;
2781 case EL_CONVEYOR_BELT4_LEFT: return GFX_BELT4_LEFT;
2782 case EL_CONVEYOR_BELT4_MIDDLE: return GFX_BELT4_MIDDLE;
2783 case EL_CONVEYOR_BELT4_RIGHT: return GFX_BELT4_RIGHT;
2784 case EL_CONVEYOR_BELT4_LEFT_ACTIVE: return GFX_BELT4_LEFT;
2785 case EL_CONVEYOR_BELT4_MIDDLE_ACTIVE:return GFX_BELT4_MIDDLE;
2786 case EL_CONVEYOR_BELT4_RIGHT_ACTIVE:return GFX_BELT4_RIGHT;
2787 case EL_CONVEYOR_BELT4_SWITCH_LEFT: return GFX_BELT4_SWITCH_LEFT;
2788 case EL_CONVEYOR_BELT4_SWITCH_MIDDLE:return GFX_BELT4_SWITCH_MIDDLE;
2789 case EL_CONVEYOR_BELT4_SWITCH_RIGHT:return GFX_BELT4_SWITCH_RIGHT;
2790 case EL_LANDMINE: return GFX_LANDMINE;
2791 case EL_ENVELOPE: return GFX_ENVELOPE;
2792 case EL_LIGHT_SWITCH: return GFX_LIGHT_SWITCH_OFF;
2793 case EL_LIGHT_SWITCH_ACTIVE: return GFX_LIGHT_SWITCH_ON;
2794 case EL_SIGN_EXCLAMATION: return GFX_SIGN_EXCLAMATION;
2795 case EL_SIGN_RADIOACTIVITY: return GFX_SIGN_RADIOACTIVITY;
2796 case EL_SIGN_STOP: return GFX_SIGN_STOP;
2797 case EL_SIGN_WHEELCHAIR: return GFX_SIGN_WHEELCHAIR;
2798 case EL_SIGN_PARKING: return GFX_SIGN_PARKING;
2799 case EL_SIGN_ONEWAY: return GFX_SIGN_ONEWAY;
2800 case EL_SIGN_HEART: return GFX_SIGN_HEART;
2801 case EL_SIGN_TRIANGLE: return GFX_SIGN_TRIANGLE;
2802 case EL_SIGN_ROUND: return GFX_SIGN_ROUND;
2803 case EL_SIGN_EXIT: return GFX_SIGN_EXIT;
2804 case EL_SIGN_YINYANG: return GFX_SIGN_YINYANG;
2805 case EL_SIGN_OTHER: return GFX_SIGN_OTHER;
2806 case EL_MOLE_LEFT: return GFX_MOLE_LEFT;
2807 case EL_MOLE_RIGHT: return GFX_MOLE_RIGHT;
2808 case EL_MOLE_UP: return GFX_MOLE_UP;
2809 case EL_MOLE_DOWN: return GFX_MOLE_DOWN;
2810 case EL_STEELWALL_SLANTED: return GFX_STEEL_SLANTED;
2811 case EL_INVISIBLE_SAND: return GFX_SAND_INVISIBLE;
2812 case EL_INVISIBLE_SAND_ACTIVE: return GFX_SAND_INVISIBLE_ON;
2813 case EL_DX_UNKNOWN_15: return GFX_DX_UNKNOWN_15;
2814 case EL_DX_UNKNOWN_42: return GFX_DX_UNKNOWN_42;
2815 case EL_TIMEGATE_OPEN: return GFX_TIMEGATE_OPEN;
2816 case EL_TIMEGATE_CLOSED: return GFX_TIMEGATE_CLOSED;
2817 case EL_TIMEGATE_SWITCH_ACTIVE: return GFX_TIMEGATE_SWITCH;
2818 case EL_TIMEGATE_SWITCH: return GFX_TIMEGATE_SWITCH;
2819 case EL_BALLOON: return GFX_BALLOON;
2820 case EL_BALLOON_SEND_LEFT: return GFX_BALLOON_SEND_LEFT;
2821 case EL_BALLOON_SEND_RIGHT: return GFX_BALLOON_SEND_RIGHT;
2822 case EL_BALLOON_SEND_UP: return GFX_BALLOON_SEND_UP;
2823 case EL_BALLOON_SEND_DOWN: return GFX_BALLOON_SEND_DOWN;
2824 case EL_BALLOON_SEND_ANY_DIRECTION: return GFX_BALLOON_SEND_ANY;
2825 case EL_EMC_STEELWALL1: return GFX_EMC_STEEL_WALL_1;
2826 case EL_EMC_STEELWALL2: return GFX_EMC_STEEL_WALL_2;
2827 case EL_EMC_STEELWALL3: return GFX_EMC_STEEL_WALL_3;
2828 case EL_EMC_STEELWALL4: return GFX_EMC_STEEL_WALL_4;
2829 case EL_EMC_WALL_PILLAR_UPPER: return GFX_EMC_WALL_1;
2830 case EL_EMC_WALL_PILLAR_MIDDLE: return GFX_EMC_WALL_2;
2831 case EL_EMC_WALL_PILLAR_LOWER: return GFX_EMC_WALL_3;
2832 case EL_EMC_WALL4: return GFX_EMC_WALL_4;
2833 case EL_EMC_WALL5: return GFX_EMC_WALL_5;
2834 case EL_EMC_WALL6: return GFX_EMC_WALL_6;
2835 case EL_EMC_WALL7: return GFX_EMC_WALL_7;
2836 case EL_EMC_WALL8: return GFX_EMC_WALL_8;
2837 case EL_TUBE_ALL: return GFX_TUBE_CROSS;
2838 case EL_TUBE_VERTICAL: return GFX_TUBE_VERTICAL;
2839 case EL_TUBE_HORIZONTAL: return GFX_TUBE_HORIZONTAL;
2840 case EL_TUBE_VERTICAL_LEFT: return GFX_TUBE_VERT_LEFT;
2841 case EL_TUBE_VERTICAL_RIGHT: return GFX_TUBE_VERT_RIGHT;
2842 case EL_TUBE_HORIZONTAL_UP: return GFX_TUBE_HORIZ_UP;
2843 case EL_TUBE_HORIZONTAL_DOWN: return GFX_TUBE_HORIZ_DOWN;
2844 case EL_TUBE_LEFT_UP: return GFX_TUBE_LEFT_UP;
2845 case EL_TUBE_LEFT_DOWN: return GFX_TUBE_LEFT_DOWN;
2846 case EL_TUBE_RIGHT_UP: return GFX_TUBE_RIGHT_UP;
2847 case EL_TUBE_RIGHT_DOWN: return GFX_TUBE_RIGHT_DOWN;
2848 case EL_SPRING: return GFX_SPRING;
2849 case EL_TRAP: return GFX_TRAP_INACTIVE;
2850 case EL_TRAP_ACTIVE: return GFX_TRAP_ACTIVE;
2851 case EL_BD_WALL: return GFX_BD_WALL;
2852 case EL_BD_ROCK: return GFX_BD_ROCK;
2853 case EL_DX_SUPABOMB: return GFX_DX_SUPABOMB;
2854 case EL_SP_MURPHY_CLONE: return GFX_SP_MURPHY_CLONE;
2858 if (IS_CHAR(element))
2859 return GFX_CHAR_START + (element - EL_CHAR_START);
2860 else if (element >= EL_SP_START && element <= EL_SP_END)
2862 int nr_element = element - EL_SP_START;
2863 int gfx_per_line = 8;
2865 (nr_element / gfx_per_line) * SP_PER_LINE +
2866 (nr_element % gfx_per_line);
2868 return GFX_START_ROCKSSP + nr_graphic;
2876 int el2gfx(int element)
2879 int graphic_OLD = el2gfx_OLD(element);
2884 int graphic_NEW = element_info[element].graphic[GFX_ACTION_DEFAULT];
2887 int graphic_OLD = el2gfx_OLD(element);
2889 if (element >= MAX_ELEMENTS)
2891 Error(ERR_WARN, "el2gfx: element == %d >= MAX_ELEMENTS", element);
2894 if (graphic_NEW != graphic_OLD)
2896 Error(ERR_WARN, "el2gfx: graphic_NEW (%d) != graphic_OLD (%d)",
2897 graphic_NEW, graphic_OLD);
2905 int el2img(int element)
2908 int graphic_NEW = element_info[element].graphic[GFX_ACTION_DEFAULT];
2911 if (graphic_NEW < 0)
2912 Error(ERR_WARN, "element %d -> graphic %d -- probably crashing now...",
2913 element, graphic_NEW);
2921 case EL_BD_BUTTERFLY: return IMG_BD_BUTTERFLY;
2922 case EL_BD_FIREFLY: return IMG_BD_FIREFLY;
2923 case EL_SP_ELECTRON: return IMG_SP_ELECTRON;
2933 int el_dir2img(int element, int direction)
2935 return el_dir_act2img(element, direction, GFX_ACTION_DEFAULT);
2938 int el_dir_act2img(int element, int direction, int action)
2940 action = graphics_action_mapping[action];
2941 direction = MV_DIR_BIT(direction);
2943 return element_info[element].direction_graphic[action][direction];