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 DrawNewScreenField(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 DrawNewLevelElement(last_jx, last_jy, Store[last_jx][last_jy]);
471 if (last_element == EL_DYNAMITE_ACTIVE)
472 DrawDynamite(last_jx, last_jy);
474 DrawNewLevelFieldThruMask(last_jx, last_jy);
476 else if (last_element == EL_DYNAMITE_ACTIVE)
477 DrawDynamite(last_jx, last_jy);
479 DrawNewLevelField(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 DrawNewLevelElement(next_jx, next_jy, EL_SOKOBAN_FIELD_EMPTY);
488 DrawNewLevelElement(next_jx, next_jy, EL_EMPTY);
491 DrawNewLevelField(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 DrawNewLevelElement(jx, jy, Store[jx][jy]);
505 else if (!IS_ACTIVE_BOMB(element))
506 DrawNewLevelField(jx, jy);
508 DrawNewLevelElement(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 = getNewGraphicAnimationFrame(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 IMG_PLAYER1_LEFT_MOVING);
570 else if (player->MovDir == MV_RIGHT)
571 graphic = (player->Pushing ? IMG_PLAYER1_RIGHT_PUSHING :
572 IMG_PLAYER1_RIGHT_MOVING);
573 else if (player->MovDir == MV_UP)
574 graphic = (player->Pushing ? IMG_PLAYER1_UP_PUSHING :
575 IMG_PLAYER1_UP_MOVING);
576 else /* MV_DOWN || MV_NO_MOVING */
577 graphic = (player->Pushing ? IMG_PLAYER1_DOWN_PUSHING :
578 IMG_PLAYER1_DOWN_MOVING);
580 graphic = PLAYER_NR_GFX(graphic, player->index_nr);
582 frame = player->Frame;
587 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
588 sxx = player->GfxPos;
590 syy = player->GfxPos;
593 if (!setup.soft_scrolling && ScreenMovPos)
596 DrawNewGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
598 if (SHIELD_ON(player))
600 int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
601 IMG_SHIELD_NORMAL_ACTIVE);
602 int frame = getNewGraphicAnimationFrame(graphic, -1);
604 DrawNewGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
607 if (player->Pushing && player->GfxPos)
609 int px = SCREENX(next_jx), py = SCREENY(next_jy);
611 if (element == EL_SOKOBAN_FIELD_EMPTY ||
612 Feld[next_jx][next_jy] == EL_SOKOBAN_FIELD_FULL)
613 DrawNewGraphicShiftedThruMask(px, py, sxx, syy, GFX_SOKOBAN_OBJEKT, 0,
617 int element = Feld[next_jx][next_jy];
618 int graphic = el2img(element);
621 if ((element == EL_ROCK ||
622 element == EL_SP_ZONK ||
623 element == EL_BD_ROCK) && sxx)
625 graphic = el_dir_act2img(element, player->MovDir, GFX_ACTION_PUSHING);
626 frame = getNewGraphicAnimationFrame(graphic, player->GfxPos);
629 if (player->MovDir == MV_LEFT)
633 frame = (player->GfxPos / (TILEX / 4));
635 if (player->MovDir == MV_RIGHT)
636 frame = (frame + 4) % 4;
640 DrawNewGraphicShifted(px, py, sxx, syy, graphic, frame,
641 NO_CUTTING, NO_MASKING);
645 /* draw things in front of player (active dynamite or dynabombs) */
647 if (IS_ACTIVE_BOMB(element))
649 graphic = el2img(element);
652 if (element == EL_DYNAMITE_ACTIVE)
654 if ((frame = (96 - MovDelay[jx][jy]) / 12) > 6)
659 if ((frame = ((96 - MovDelay[jx][jy]) / 6) % 8) > 3)
663 frame = getNewGraphicAnimationFrame(graphic, 96 - MovDelay[jx][jy]);
666 if (game.emulation == EMU_SUPAPLEX)
667 DrawNewGraphic(sx, sy, GFX_SP_DISK_RED, 0);
669 DrawNewGraphicThruMask(sx, sy, graphic, frame);
672 if (player_is_moving && last_element == EL_EXPLOSION)
674 int frame = Frame[last_jx][last_jy];
678 DrawNewGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy),
679 GFX_EXPLOSION, ((frame - 1) / delay - 1));
682 /* draw elements that stay over the player */
683 /* handle the field the player is leaving ... */
684 if (player_is_moving && IS_OVER_PLAYER(last_element))
685 DrawNewLevelField(last_jx, last_jy);
686 /* ... and the field the player is entering */
687 if (IS_OVER_PLAYER(element))
688 DrawNewLevelField(jx, jy);
690 if (setup.direct_draw)
692 int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
693 int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
694 int x_size = TILEX * (1 + ABS(jx - last_jx));
695 int y_size = TILEY * (1 + ABS(jy - last_jy));
697 BlitBitmap(drawto_field, window,
698 dest_x, dest_y, x_size, y_size, dest_x, dest_y);
699 SetDrawtoField(DRAW_DIRECT);
702 MarkTileDirty(sx,sy);
705 static int getGraphicAnimationPhase(int frames, int delay, int mode)
709 if (mode & ANIM_PINGPONG)
711 int max_anim_frames = 2 * frames - 2;
713 phase = (FrameCounter % (delay * max_anim_frames)) / delay;
714 phase = (phase < frames ? phase : max_anim_frames - phase);
717 phase = (FrameCounter % (delay * frames)) / delay;
719 if (mode & ANIM_REVERSE)
725 int getNewGraphicAnimationFrame(int graphic, int sync_frame)
727 int num_frames = new_graphic_info[graphic].anim_frames;
728 int delay = new_graphic_info[graphic].anim_delay;
729 int mode = new_graphic_info[graphic].anim_mode;
732 /* animation synchronized with global frame counter, not move position */
733 if (new_graphic_info[graphic].anim_global_sync || sync_frame < 0)
734 sync_frame = FrameCounter;
736 if (mode & ANIM_LOOP) /* normal, looping animation */
738 frame = (sync_frame % (delay * num_frames)) / delay;
740 else if (mode & ANIM_LINEAR) /* normal, non-looping animation */
742 frame = sync_frame / delay;
744 if (frame > num_frames - 1)
745 frame = num_frames - 1;
747 else if (mode & ANIM_PINGPONG) /* use border frames once */
749 int max_anim_frames = 2 * num_frames - 2;
751 frame = (sync_frame % (delay * max_anim_frames)) / delay;
752 frame = (frame < num_frames ? frame : max_anim_frames - frame);
754 else if (mode & ANIM_PINGPONG2) /* use border frames twice */
756 int max_anim_frames = 2 * num_frames;
758 frame = (sync_frame % (delay * max_anim_frames)) / delay;
759 frame = (frame < num_frames ? frame : max_anim_frames - frame - 1);
762 if (mode & ANIM_REVERSE) /* use reverse animation direction */
763 frame = num_frames - frame - 1;
768 void DrawNewGraphicAnimationExt(int x, int y, int graphic, int mask_mode)
771 int delay = new_graphic_info[graphic].anim_delay;
773 if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
775 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
778 int frame = getNewGraphicAnimationFrame(graphic, -1);
780 if (mask_mode == USE_MASKING)
781 DrawNewGraphicThruMask(SCREENX(x), SCREENY(y), graphic, frame);
783 DrawNewGraphic(SCREENX(x), SCREENY(y), graphic, frame);
788 void DrawOldGraphicAnimation(int x, int y, int graphic,
789 int frames, int delay, int mode)
791 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, NO_MASKING);
795 void DrawNewGraphicAnimation(int x, int y, int graphic)
797 DrawNewGraphicAnimationExt(x, y, graphic, NO_MASKING);
801 void getOldGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
803 if (graphic >= 0 && graphic_info[graphic].bitmap != NULL)
805 *bitmap = graphic_info[graphic].bitmap;
806 *x = graphic_info[graphic].src_x;
807 *y = graphic_info[graphic].src_y;
809 else if (graphic >= GFX_START_ROCKSELEMENTS &&
810 graphic <= GFX_END_ROCKSELEMENTS)
812 graphic -= GFX_START_ROCKSELEMENTS;
813 *bitmap = pix[PIX_ELEMENTS];
814 *x = (graphic % GFX_PER_LINE) * TILEX;
815 *y = (graphic / GFX_PER_LINE) * TILEY;
817 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
819 graphic -= GFX_START_ROCKSHEROES;
820 *bitmap = pix[PIX_HEROES];
821 *x = (graphic % HEROES_PER_LINE) * TILEX;
822 *y = (graphic / HEROES_PER_LINE) * TILEY;
824 else if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
826 graphic -= GFX_START_ROCKSSP;
827 *bitmap = pix[PIX_SP];
828 *x = (graphic % SP_PER_LINE) * TILEX;
829 *y = (graphic / SP_PER_LINE) * TILEY;
831 else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
833 graphic -= GFX_START_ROCKSDC;
834 *bitmap = pix[PIX_DC];
835 *x = (graphic % DC_PER_LINE) * TILEX;
836 *y = (graphic / DC_PER_LINE) * TILEY;
838 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
840 graphic -= GFX_START_ROCKSMORE;
841 *bitmap = pix[PIX_MORE];
842 *x = (graphic % MORE_PER_LINE) * TILEX;
843 *y = (graphic / MORE_PER_LINE) * TILEY;
845 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
847 graphic -= GFX_START_ROCKSFONT;
848 *bitmap = pix[PIX_FONT_EM];
849 *x = (graphic % FONT_CHARS_PER_LINE) * TILEX;
850 *y = (graphic / FONT_CHARS_PER_LINE) * TILEY;
854 *bitmap = pix[PIX_SP];
861 void DrawNewGraphic(int x, int y, int graphic, int frame)
864 if (!IN_SCR_FIELD(x, y))
866 printf("DrawNewGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
867 printf("DrawNewGraphic(): This should never happen!\n");
872 DrawNewGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
877 void DrawOldGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic)
882 getOldGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
883 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
886 void DrawNewGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
889 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
890 int src_x = new_graphic_info[graphic].src_x;
891 int src_y = new_graphic_info[graphic].src_y;
892 int offset_x = new_graphic_info[graphic].offset_x;
893 int offset_y = new_graphic_info[graphic].offset_y;
895 src_x += frame * offset_x;
896 src_y += frame * offset_y;
898 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
901 void DrawNewGraphicThruMask(int x, int y, int graphic, int frame)
904 if (!IN_SCR_FIELD(x, y))
906 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
907 printf("DrawGraphicThruMask(): This should never happen!\n");
912 DrawNewGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY,
917 void DrawNewGraphicThruMaskExt(DrawBuffer *d, int dest_x, int dest_y,
918 int graphic, int frame)
920 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
921 GC drawing_gc = src_bitmap->stored_clip_gc;
922 int src_x = new_graphic_info[graphic].src_x;
923 int src_y = new_graphic_info[graphic].src_y;
924 int offset_x = new_graphic_info[graphic].offset_x;
925 int offset_y = new_graphic_info[graphic].offset_y;
927 src_x += frame * offset_x;
928 src_y += frame * offset_y;
930 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
931 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dest_x, dest_y);
934 void DrawNewMiniGraphic(int x, int y, int graphic)
936 DrawNewMiniGraphicExt(drawto,
937 SX + x * MINI_TILEX, SY + y * MINI_TILEY, graphic);
938 MarkTileDirty(x / 2, y / 2);
941 void getNewMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
943 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
945 int mini_starty = src_bitmap->height * 2 / 3;
946 int src_x = mini_startx + new_graphic_info[graphic].src_x / 2;
947 int src_y = mini_starty + new_graphic_info[graphic].src_y / 2;
949 *bitmap = src_bitmap;
954 void DrawNewMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
959 getNewMiniGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
960 BlitBitmap(src_bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
963 void DrawNewGraphicShifted(int x,int y, int dx,int dy, int graphic, int frame,
964 int cut_mode, int mask_mode)
973 int width = TILEX, height = TILEY;
979 DrawNewGraphic(x, y, graphic, frame);
983 if (dx || dy) /* shifted graphic */
985 if (x < BX1) /* object enters playfield from the left */
992 else if (x > BX2) /* object enters playfield from the right */
998 else if (x==BX1 && dx < 0) /* object leaves playfield to the left */
1004 else if (x==BX2 && dx > 0) /* object leaves playfield to the right */
1006 else if (dx) /* general horizontal movement */
1007 MarkTileDirty(x + SIGN(dx), y);
1009 if (y < BY1) /* object enters playfield from the top */
1011 if (cut_mode==CUT_BELOW) /* object completely above top border */
1019 else if (y > BY2) /* object enters playfield from the bottom */
1025 else if (y==BY1 && dy < 0) /* object leaves playfield to the top */
1031 else if (dy > 0 && cut_mode == CUT_ABOVE)
1033 if (y == BY2) /* object completely above bottom border */
1039 MarkTileDirty(x, y + 1);
1040 } /* object leaves playfield to the bottom */
1041 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1043 else if (dy) /* general vertical movement */
1044 MarkTileDirty(x, y + SIGN(dy));
1047 src_bitmap = new_graphic_info[graphic].bitmap;
1048 src_x = new_graphic_info[graphic].src_x;
1049 src_y = new_graphic_info[graphic].src_y;
1050 offset_x = new_graphic_info[graphic].offset_x;
1051 offset_y = new_graphic_info[graphic].offset_y;
1053 drawing_gc = src_bitmap->stored_clip_gc;
1055 src_x += frame * offset_x;
1056 src_y += frame * offset_y;
1061 dest_x = FX + x * TILEX + dx;
1062 dest_y = FY + y * TILEY + dy;
1065 if (!IN_SCR_FIELD(x,y))
1067 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1068 printf("DrawGraphicShifted(): This should never happen!\n");
1073 if (mask_mode == USE_MASKING)
1075 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1076 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
1080 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1086 void DrawNewGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
1087 int frame, int cut_mode)
1089 DrawNewGraphicShifted(x,y, dx,dy, graphic, frame, cut_mode, USE_MASKING);
1093 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1094 int cut_mode, int mask_mode)
1096 int ux = LEVELX(x), uy = LEVELY(y);
1097 int graphic = el2gfx(element);
1098 int phase8 = ABS(MovPos[ux][uy]) / (TILEX / 8);
1099 int phase4 = phase8 / 2;
1100 int phase2 = phase8 / 4;
1101 int dir = MovDir[ux][uy];
1103 if (element == EL_PACMAN || element == EL_BUG || element == EL_SPACESHIP)
1105 graphic += 1 * !phase2;
1109 else if (dir == MV_LEFT)
1111 else if (dir == MV_DOWN)
1114 else if (element == EL_SP_SNIKSNAK)
1117 graphic = GFX_SP_SNIKSNAK_LEFT;
1118 else if (dir == MV_RIGHT)
1119 graphic = GFX_SP_SNIKSNAK_RIGHT;
1120 else if (dir == MV_UP)
1121 graphic = GFX_SP_SNIKSNAK_UP;
1123 graphic = GFX_SP_SNIKSNAK_DOWN;
1125 graphic += (phase8 < 4 ? phase8 : 7 - phase8);
1127 else if (element == EL_SP_ELECTRON)
1129 graphic = GFX2_SP_ELECTRON + getGraphicAnimationPhase(8, 2, ANIM_LOOP);
1131 else if (element == EL_MOLE || element == EL_PENGUIN ||
1132 element == EL_PIG || element == EL_DRAGON)
1135 graphic = (element == EL_MOLE ? GFX_MOLE_LEFT :
1136 element == EL_PENGUIN ? GFX_PINGUIN_LEFT :
1137 element == EL_PIG ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
1138 else if (dir == MV_RIGHT)
1139 graphic = (element == EL_MOLE ? GFX_MOLE_RIGHT :
1140 element == EL_PENGUIN ? GFX_PINGUIN_RIGHT :
1141 element == EL_PIG ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
1142 else if (dir == MV_UP)
1143 graphic = (element == EL_MOLE ? GFX_MOLE_UP :
1144 element == EL_PENGUIN ? GFX_PINGUIN_UP :
1145 element == EL_PIG ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
1147 graphic = (element == EL_MOLE ? GFX_MOLE_DOWN :
1148 element == EL_PENGUIN ? GFX_PINGUIN_DOWN :
1149 element == EL_PIG ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
1153 else if (element == EL_SATELLITE)
1155 graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_LOOP);
1157 else if (element == EL_ACID)
1159 graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_LOOP);
1161 else if (element == EL_BD_BUTTERFLY || element == EL_BD_FIREFLY)
1165 else if (element == EL_BALLOON)
1169 else if ((element == EL_ROCK ||
1170 element == EL_SP_ZONK ||
1171 element == EL_BD_ROCK ||
1172 element == EL_SP_INFOTRON ||
1176 if (uy >= lev_fieldy-1 || !IS_BELT(Feld[ux][uy+1]))
1178 if (element == EL_ROCK ||
1179 element == EL_SP_ZONK ||
1180 element == EL_BD_ROCK)
1183 graphic += (4 - phase4) % 4;
1184 else if (dir == MV_RIGHT)
1187 graphic += phase2 * 2;
1189 else if (element != EL_SP_INFOTRON)
1193 else if (element == EL_MAGIC_WALL_ACTIVE ||
1194 element == EL_MAGIC_WALL_EMPTYING ||
1195 element == EL_BD_MAGIC_WALL_ACTIVE ||
1196 element == EL_BD_MAGIC_WALL_EMPTYING ||
1197 element == EL_MAGIC_WALL_FULL ||
1198 element == EL_BD_MAGIC_WALL_FULL)
1200 graphic += 3 + getGraphicAnimationPhase(4, 4, ANIM_REVERSE);
1202 else if (IS_AMOEBOID(element) || element == EL_AMOEBA_DRIPPING)
1204 graphic = (element == EL_AMOEBA_DEAD ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
1205 graphic += (x + 2 * y + 4) % 4;
1207 else if (element == EL_WALL_GROWING)
1209 boolean links_massiv = FALSE, rechts_massiv = FALSE;
1211 if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
1212 links_massiv = TRUE;
1213 if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
1214 rechts_massiv = TRUE;
1216 if (links_massiv && rechts_massiv)
1217 graphic = GFX_MAUERWERK;
1218 else if (links_massiv)
1219 graphic = GFX_MAUER_R;
1220 else if (rechts_massiv)
1221 graphic = GFX_MAUER_L;
1224 else if ((element == EL_INVISIBLE_STEELWALL ||
1225 element == EL_INVISIBLE_WALL ||
1226 element == EL_INVISIBLE_SAND) && game.light_time_left)
1228 graphic = (element == EL_INVISIBLE_STEELWALL ? GFX_INVISIBLE_STEEL_ON :
1229 element == EL_INVISIBLE_WALL ? GFX_UNSICHTBAR_ON :
1230 GFX_SAND_INVISIBLE_ON);
1235 DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
1236 else if (mask_mode == USE_MASKING)
1237 DrawGraphicThruMask(x, y, graphic);
1239 DrawGraphic(x, y, graphic);
1243 inline static int getFramePosition(int x, int y)
1245 int element = Feld[x][y];
1248 if (element == EL_QUICKSAND_FULL ||
1249 element == EL_MAGIC_WALL_FULL ||
1250 element == EL_BD_MAGIC_WALL_FULL)
1252 else if (IS_MOVING(x, y) || CAN_MOVE(element) || CAN_FALL(element))
1253 frame_pos = ABS(MovPos[x][y]) / (TILEX / 8);
1258 inline static int getGfxAction(int x, int y)
1260 int gfx_action = GFX_ACTION_DEFAULT;
1262 if (GfxAction[x][y] != GFX_ACTION_DEFAULT)
1263 gfx_action = GfxAction[x][y];
1264 else if (IS_MOVING(x, y))
1265 gfx_action = GFX_ACTION_MOVING;
1270 void DrawNewScreenElementExt(int x, int y, int dx, int dy, int element,
1271 int cut_mode, int mask_mode)
1273 int ux = LEVELX(x), uy = LEVELY(y);
1274 int move_dir = MovDir[ux][uy];
1275 int move_pos = getFramePosition(ux, uy);
1276 int gfx_action = getGfxAction(ux, uy);
1277 int graphic = el_dir_act2img(element, move_dir, gfx_action);
1278 int frame = getNewGraphicAnimationFrame(graphic, move_pos);
1280 if (element == EL_WALL_GROWING)
1282 boolean left_stopped = FALSE, right_stopped = FALSE;
1284 if (!IN_LEV_FIELD(ux - 1, uy) || IS_MAUER(Feld[ux - 1][uy]))
1285 left_stopped = TRUE;
1286 if (!IN_LEV_FIELD(ux + 1, uy) || IS_MAUER(Feld[ux + 1][uy]))
1287 right_stopped = TRUE;
1289 if (left_stopped && right_stopped)
1291 else if (left_stopped)
1293 graphic = IMG_WALL_GROWING_ACTIVE_RIGHT;
1294 frame = new_graphic_info[graphic].anim_frames - 1;
1296 else if (right_stopped)
1298 graphic = IMG_WALL_GROWING_ACTIVE_LEFT;
1299 frame = new_graphic_info[graphic].anim_frames - 1;
1303 else if ((element == EL_ROCK ||
1304 element == EL_SP_ZONK ||
1305 element == EL_BD_ROCK ||
1306 element == EL_SP_INFOTRON ||
1310 if (uy >= lev_fieldy-1 || !IS_BELT(Feld[ux][uy+1]))
1312 if (element == EL_ROCK ||
1313 element == EL_SP_ZONK ||
1314 element == EL_BD_ROCK)
1316 if (move_dir == MV_LEFT)
1317 graphic += (4 - phase4) % 4;
1318 else if (move_dir == MV_RIGHT)
1321 graphic += phase2 * 2;
1323 else if (element != EL_SP_INFOTRON)
1328 else if (IS_AMOEBOID(element) || element == EL_AMOEBA_DRIPPING)
1330 graphic = (element == EL_BD_AMOEBA ? IMG_BD_AMOEBA_PART1 :
1331 element == EL_AMOEBA_WET ? IMG_AMOEBA_WET_PART1 :
1332 element == EL_AMOEBA_DRY ? IMG_AMOEBA_DRY_PART1 :
1333 element == EL_AMOEBA_FULL ? IMG_AMOEBA_FULL_PART1 :
1334 IMG_AMOEBA_DEAD_PART1);
1336 graphic += (x + 2 * y + 4) % 4;
1340 DrawNewGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
1341 else if (mask_mode == USE_MASKING)
1342 DrawNewGraphicThruMask(x, y, graphic, frame);
1344 DrawNewGraphic(x, y, graphic, frame);
1347 void DrawNewLevelElementExt(int x, int y, int dx, int dy, int element,
1348 int cut_mode, int mask_mode)
1350 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1351 DrawNewScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1352 cut_mode, mask_mode);
1355 void DrawNewScreenElementShifted(int x, int y, int dx, int dy, int element,
1358 DrawNewScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1361 void DrawNewLevelElementShifted(int x, int y, int dx, int dy, int element,
1364 DrawNewLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1368 void DrawScreenElementThruMask(int x, int y, int element)
1370 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1373 void DrawNewScreenElementThruMask(int x, int y, int element)
1375 DrawNewScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1379 void DrawNewLevelElementThruMask(int x, int y, int element)
1381 DrawNewLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1384 void DrawNewLevelFieldThruMask(int x, int y)
1386 DrawNewLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1389 void DrawCrumbledSand(int x, int y)
1393 int i, width, height, cx,cy;
1394 int ux = LEVELX(x), uy = LEVELY(y);
1395 int element, graphic;
1397 static int xy[4][2] =
1405 if (!IN_LEV_FIELD(ux, uy))
1408 element = Feld[ux][uy];
1410 if (element == EL_SAND ||
1411 element == EL_LANDMINE ||
1412 element == EL_TRAP ||
1413 element == EL_TRAP_ACTIVE)
1415 if (!IN_SCR_FIELD(x, y))
1418 graphic = IMG_SAND_CRUMBLED;
1420 src_bitmap = new_graphic_info[graphic].bitmap;
1421 src_x = new_graphic_info[graphic].src_x;
1422 src_y = new_graphic_info[graphic].src_y;
1428 uxx = ux + xy[i][0];
1429 uyy = uy + xy[i][1];
1430 if (!IN_LEV_FIELD(uxx, uyy))
1431 element = EL_STEELWALL;
1433 element = Feld[uxx][uyy];
1435 if (element == EL_SAND ||
1436 element == EL_LANDMINE ||
1437 element == EL_TRAP ||
1438 element == EL_TRAP_ACTIVE)
1441 if (i == 1 || i == 2)
1445 cx = (i == 2 ? TILEX - snip : 0);
1453 cy = (i == 3 ? TILEY - snip : 0);
1456 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1457 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1460 MarkTileDirty(x, y);
1464 graphic = IMG_SAND_CRUMBLED;
1466 src_bitmap = new_graphic_info[graphic].bitmap;
1467 src_x = new_graphic_info[graphic].src_x;
1468 src_y = new_graphic_info[graphic].src_y;
1472 int xx, yy, uxx, uyy;
1476 uxx = ux + xy[i][0];
1477 uyy = uy + xy[i][1];
1479 if (!IN_LEV_FIELD(uxx, uyy) ||
1480 (Feld[uxx][uyy] != EL_SAND &&
1481 Feld[uxx][uyy] != EL_LANDMINE &&
1482 Feld[uxx][uyy] != EL_TRAP &&
1483 Feld[uxx][uyy] != EL_TRAP_ACTIVE) ||
1484 !IN_SCR_FIELD(xx, yy))
1487 if (i == 1 || i == 2)
1491 cx = (i == 1 ? TILEX - snip : 0);
1499 cy = (i==0 ? TILEY-snip : 0);
1502 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1503 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1505 MarkTileDirty(xx, yy);
1510 void DrawNewScreenElement(int x, int y, int element)
1512 DrawNewScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1513 DrawCrumbledSand(x, y);
1516 void DrawNewLevelElement(int x, int y, int element)
1518 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1519 DrawNewScreenElement(SCREENX(x), SCREENY(y), element);
1522 void DrawNewScreenField(int x, int y)
1524 int ux = LEVELX(x), uy = LEVELY(y);
1525 int element, content;
1527 if (!IN_LEV_FIELD(ux, uy))
1529 if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
1532 element = BorderElement;
1534 DrawNewScreenElement(x, y, element);
1538 element = Feld[ux][uy];
1539 content = Store[ux][uy];
1541 if (IS_MOVING(ux, uy))
1543 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1544 boolean cut_mode = NO_CUTTING;
1546 if (element == EL_QUICKSAND_EMPTYING ||
1547 element == EL_MAGIC_WALL_EMPTYING ||
1548 element == EL_BD_MAGIC_WALL_EMPTYING ||
1549 element == EL_AMOEBA_DRIPPING)
1550 cut_mode = CUT_ABOVE;
1551 else if (element == EL_QUICKSAND_FILLING ||
1552 element == EL_MAGIC_WALL_FILLING ||
1553 element == EL_BD_MAGIC_WALL_FILLING)
1554 cut_mode = CUT_BELOW;
1556 if (cut_mode == CUT_ABOVE)
1557 DrawNewScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1559 DrawNewScreenElement(x, y, EL_EMPTY);
1562 DrawNewScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1563 else if (cut_mode == NO_CUTTING)
1564 DrawNewScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1566 DrawNewScreenElementShifted(x, y, 0, MovPos[ux][uy], content, cut_mode);
1568 if (content == EL_ACID)
1569 DrawNewLevelElementThruMask(ux, uy + 1, EL_ACID);
1571 else if (IS_BLOCKED(ux, uy))
1576 boolean cut_mode = NO_CUTTING;
1577 int element_old, content_old;
1579 Blocked2Moving(ux, uy, &oldx, &oldy);
1582 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1583 MovDir[oldx][oldy] == MV_RIGHT);
1585 element_old = Feld[oldx][oldy];
1586 content_old = Store[oldx][oldy];
1588 if (element_old == EL_QUICKSAND_EMPTYING ||
1589 element_old == EL_MAGIC_WALL_EMPTYING ||
1590 element_old == EL_BD_MAGIC_WALL_EMPTYING ||
1591 element_old == EL_AMOEBA_DRIPPING)
1592 cut_mode = CUT_ABOVE;
1594 DrawNewScreenElement(x, y, EL_EMPTY);
1597 DrawNewScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
1599 else if (cut_mode == NO_CUTTING)
1600 DrawNewScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
1603 DrawNewScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
1606 else if (IS_DRAWABLE(element))
1607 DrawNewScreenElement(x, y, element);
1609 DrawNewScreenElement(x, y, EL_EMPTY);
1612 void DrawNewLevelField(int x, int y)
1614 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1615 DrawNewScreenField(SCREENX(x), SCREENY(y));
1616 else if (IS_MOVING(x, y))
1620 Moving2Blocked(x, y, &newx, &newy);
1621 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1622 DrawNewScreenField(SCREENX(newx), SCREENY(newy));
1624 else if (IS_BLOCKED(x, y))
1628 Blocked2Moving(x, y, &oldx, &oldy);
1629 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1630 DrawNewScreenField(SCREENX(oldx), SCREENY(oldy));
1634 void DrawNewMiniElement(int x, int y, int element)
1638 graphic = el2img(element);
1639 DrawNewMiniGraphic(x, y, graphic);
1642 void DrawNewMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1644 int x = sx + scroll_x, y = sy + scroll_y;
1646 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1647 DrawNewMiniElement(sx, sy, EL_EMPTY);
1648 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1649 DrawNewMiniElement(sx, sy, Feld[x][y]);
1652 int steel_type, steel_position;
1655 { IMG_STEELWALL_TOPLEFT, IMG_INVISIBLE_STEELWALL_TOPLEFT },
1656 { IMG_STEELWALL_TOPRIGHT, IMG_INVISIBLE_STEELWALL_TOPRIGHT },
1657 { IMG_STEELWALL_BOTTOMLEFT, IMG_INVISIBLE_STEELWALL_BOTTOMLEFT },
1658 { IMG_STEELWALL_BOTTOMRIGHT, IMG_INVISIBLE_STEELWALL_BOTTOMRIGHT },
1659 { IMG_STEELWALL_VERTICAL, IMG_INVISIBLE_STEELWALL_VERTICAL },
1660 { IMG_STEELWALL_HORIZONTAL, IMG_INVISIBLE_STEELWALL_HORIZONTAL }
1663 steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
1664 steel_position = (x == -1 && y == -1 ? 0 :
1665 x == lev_fieldx && y == -1 ? 1 :
1666 x == -1 && y == lev_fieldy ? 2 :
1667 x == lev_fieldx && y == lev_fieldy ? 3 :
1668 x == -1 || x == lev_fieldx ? 4 :
1669 y == -1 || y == lev_fieldy ? 5 : -1);
1671 if (steel_position != -1)
1672 DrawNewMiniGraphic(sx, sy, border[steel_position][steel_type]);
1676 void getNewMicroGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1678 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
1679 int mini_startx = src_bitmap->width * 3 / 4;
1680 int mini_starty = src_bitmap->height * 2 / 3;
1681 int src_x = mini_startx + new_graphic_info[graphic].src_x / 8;
1682 int src_y = mini_starty + new_graphic_info[graphic].src_y / 8;
1684 *bitmap = src_bitmap;
1689 void DrawNewMicroElement(int xpos, int ypos, int element)
1695 if (element == EL_EMPTY)
1698 graphic = el2img(element);
1700 getNewMicroGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1701 BlitBitmap(src_bitmap, drawto, src_x, src_y, MICRO_TILEX, MICRO_TILEY,
1711 for(x=BX1; x<=BX2; x++)
1712 for(y=BY1; y<=BY2; y++)
1713 DrawNewScreenField(x, y);
1715 redraw_mask |= REDRAW_FIELD;
1718 void DrawNewMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1722 for(x=0; x<size_x; x++)
1723 for(y=0; y<size_y; y++)
1724 DrawNewMiniElementOrWall(x, y, scroll_x, scroll_y);
1726 redraw_mask |= REDRAW_FIELD;
1729 static void DrawNewMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1733 ClearRectangle(drawto, xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
1735 if (lev_fieldx < STD_LEV_FIELDX)
1736 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1737 if (lev_fieldy < STD_LEV_FIELDY)
1738 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1740 xpos += MICRO_TILEX;
1741 ypos += MICRO_TILEY;
1743 for(x=-1; x<=STD_LEV_FIELDX; x++)
1745 for(y=-1; y<=STD_LEV_FIELDY; y++)
1747 int lx = from_x + x, ly = from_y + y;
1749 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1750 DrawNewMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1752 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1)
1753 DrawNewMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1758 redraw_mask |= REDRAW_MICROLEVEL;
1761 #define MICROLABEL_EMPTY 0
1762 #define MICROLABEL_LEVEL_NAME 1
1763 #define MICROLABEL_CREATED_BY 2
1764 #define MICROLABEL_LEVEL_AUTHOR 3
1765 #define MICROLABEL_IMPORTED_FROM 4
1766 #define MICROLABEL_LEVEL_IMPORT_INFO 5
1768 #define MAX_MICROLABEL_SIZE (SXSIZE / FONT4_XSIZE)
1770 static void DrawMicroLevelLabelExt(int mode)
1772 char label_text[MAX_MICROLABEL_SIZE + 1];
1774 ClearRectangle(drawto, SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
1776 strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
1777 mode == MICROLABEL_CREATED_BY ? "created by" :
1778 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
1779 mode == MICROLABEL_IMPORTED_FROM ? "imported from" :
1780 mode == MICROLABEL_LEVEL_IMPORT_INFO ?
1781 leveldir_current->imported_from : ""),
1782 MAX_MICROLABEL_SIZE);
1783 label_text[MAX_MICROLABEL_SIZE] = '\0';
1785 if (strlen(label_text) > 0)
1787 int lxpos = SX + (SXSIZE - strlen(label_text) * FONT4_XSIZE) / 2;
1788 int lypos = MICROLABEL_YPOS;
1790 DrawText(lxpos, lypos, label_text, FS_SMALL, FC_SPECIAL2);
1793 redraw_mask |= REDRAW_MICROLEVEL;
1796 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1798 static unsigned long scroll_delay = 0;
1799 static unsigned long label_delay = 0;
1800 static int from_x, from_y, scroll_direction;
1801 static int label_state, label_counter;
1805 from_x = from_y = 0;
1806 scroll_direction = MV_RIGHT;
1810 DrawNewMicroLevelExt(xpos, ypos, from_x, from_y);
1811 DrawMicroLevelLabelExt(label_state);
1813 /* initialize delay counters */
1814 DelayReached(&scroll_delay, 0);
1815 DelayReached(&label_delay, 0);
1820 /* scroll micro level, if needed */
1821 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1822 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1824 switch (scroll_direction)
1830 scroll_direction = MV_UP;
1834 if (from_x < lev_fieldx - STD_LEV_FIELDX)
1837 scroll_direction = MV_DOWN;
1844 scroll_direction = MV_RIGHT;
1848 if (from_y < lev_fieldy - STD_LEV_FIELDY)
1851 scroll_direction = MV_LEFT;
1858 DrawNewMicroLevelExt(xpos, ypos, from_x, from_y);
1861 /* redraw micro level label, if needed */
1862 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1863 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1864 strcmp(level.author, leveldir_current->name) != 0 &&
1865 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1867 int max_label_counter = 23;
1869 if (leveldir_current->imported_from != NULL)
1870 max_label_counter += 14;
1872 label_counter = (label_counter + 1) % max_label_counter;
1873 label_state = (label_counter >= 0 && label_counter <= 7 ?
1874 MICROLABEL_LEVEL_NAME :
1875 label_counter >= 9 && label_counter <= 12 ?
1876 MICROLABEL_CREATED_BY :
1877 label_counter >= 14 && label_counter <= 21 ?
1878 MICROLABEL_LEVEL_AUTHOR :
1879 label_counter >= 23 && label_counter <= 26 ?
1880 MICROLABEL_IMPORTED_FROM :
1881 label_counter >= 28 && label_counter <= 35 ?
1882 MICROLABEL_LEVEL_IMPORT_INFO : MICROLABEL_EMPTY);
1883 DrawMicroLevelLabelExt(label_state);
1887 int REQ_in_range(int x, int y)
1889 if (y > DY+249 && y < DY+278)
1891 if (x > DX+1 && x < DX+48)
1893 else if (x > DX+51 && x < DX+98)
1899 #define MAX_REQUEST_LINES 13
1900 #define MAX_REQUEST_LINE_LEN 7
1902 boolean Request(char *text, unsigned int req_state)
1904 int mx, my, ty, result = -1;
1905 unsigned int old_door_state;
1907 #if defined(PLATFORM_UNIX)
1908 /* pause network game while waiting for request to answer */
1909 if (options.network &&
1910 game_status == PLAYING &&
1911 req_state & REQUEST_WAIT_FOR)
1912 SendToServer_PausePlaying();
1915 old_door_state = GetDoorState();
1919 CloseDoor(DOOR_CLOSE_1);
1921 /* save old door content */
1922 BlitBitmap(pix[PIX_DB_DOOR], pix[PIX_DB_DOOR],
1923 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
1924 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
1926 /* clear door drawing field */
1927 ClearRectangle(drawto, DX, DY, DXSIZE, DYSIZE);
1929 /* write text for request */
1930 for(ty=0; ty < MAX_REQUEST_LINES; ty++)
1932 char text_line[MAX_REQUEST_LINE_LEN + 1];
1938 for(tl=0,tx=0; tx < MAX_REQUEST_LINE_LEN; tl++,tx++)
1941 if (!tc || tc == ' ')
1952 strncpy(text_line, text, tl);
1955 DrawTextExt(drawto, DX + 50 - (tl * 14)/2, DY + 8 + ty * 16,
1956 text_line, FS_SMALL, FC_YELLOW);
1958 text += tl + (tc == ' ' ? 1 : 0);
1961 if (req_state & REQ_ASK)
1963 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
1964 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
1966 else if (req_state & REQ_CONFIRM)
1968 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
1970 else if (req_state & REQ_PLAYER)
1972 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
1973 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
1974 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
1975 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
1978 /* copy request gadgets to door backbuffer */
1979 BlitBitmap(drawto, pix[PIX_DB_DOOR],
1980 DX, DY, DXSIZE, DYSIZE,
1981 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1983 OpenDoor(DOOR_OPEN_1);
1989 if (!(req_state & REQUEST_WAIT_FOR))
1992 if (game_status != MAINMENU)
1995 button_status = MB_RELEASED;
1997 request_gadget_id = -1;
2009 case EVENT_BUTTONPRESS:
2010 case EVENT_BUTTONRELEASE:
2011 case EVENT_MOTIONNOTIFY:
2013 if (event.type == EVENT_MOTIONNOTIFY)
2015 if (!PointerInWindow(window))
2016 continue; /* window and pointer are on different screens */
2021 motion_status = TRUE;
2022 mx = ((MotionEvent *) &event)->x;
2023 my = ((MotionEvent *) &event)->y;
2027 motion_status = FALSE;
2028 mx = ((ButtonEvent *) &event)->x;
2029 my = ((ButtonEvent *) &event)->y;
2030 if (event.type == EVENT_BUTTONPRESS)
2031 button_status = ((ButtonEvent *) &event)->button;
2033 button_status = MB_RELEASED;
2036 /* this sets 'request_gadget_id' */
2037 HandleGadgets(mx, my, button_status);
2039 switch(request_gadget_id)
2041 case TOOL_CTRL_ID_YES:
2044 case TOOL_CTRL_ID_NO:
2047 case TOOL_CTRL_ID_CONFIRM:
2048 result = TRUE | FALSE;
2051 case TOOL_CTRL_ID_PLAYER_1:
2054 case TOOL_CTRL_ID_PLAYER_2:
2057 case TOOL_CTRL_ID_PLAYER_3:
2060 case TOOL_CTRL_ID_PLAYER_4:
2071 case EVENT_KEYPRESS:
2072 switch(GetEventKey((KeyEvent *)&event, TRUE))
2085 if (req_state & REQ_PLAYER)
2089 case EVENT_KEYRELEASE:
2090 ClearPlayerAction();
2094 HandleOtherEvents(&event);
2098 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2100 int joy = AnyJoystick();
2102 if (joy & JOY_BUTTON_1)
2104 else if (joy & JOY_BUTTON_2)
2110 /* don't eat all CPU time */
2114 if (game_status != MAINMENU)
2119 if (!(req_state & REQ_STAY_OPEN))
2121 CloseDoor(DOOR_CLOSE_1);
2123 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
2125 BlitBitmap(pix[PIX_DB_DOOR], pix[PIX_DB_DOOR],
2126 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
2127 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
2128 OpenDoor(DOOR_OPEN_1);
2134 #if defined(PLATFORM_UNIX)
2135 /* continue network game after request */
2136 if (options.network &&
2137 game_status == PLAYING &&
2138 req_state & REQUEST_WAIT_FOR)
2139 SendToServer_ContinuePlaying();
2145 unsigned int OpenDoor(unsigned int door_state)
2147 unsigned int new_door_state;
2149 if (door_state & DOOR_COPY_BACK)
2151 BlitBitmap(pix[PIX_DB_DOOR], pix[PIX_DB_DOOR],
2152 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
2153 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2154 door_state &= ~DOOR_COPY_BACK;
2157 new_door_state = MoveDoor(door_state);
2159 return(new_door_state);
2162 unsigned int CloseDoor(unsigned int door_state)
2164 unsigned int new_door_state;
2166 BlitBitmap(backbuffer, pix[PIX_DB_DOOR],
2167 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2168 BlitBitmap(backbuffer, pix[PIX_DB_DOOR],
2169 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2171 new_door_state = MoveDoor(door_state);
2173 return(new_door_state);
2176 unsigned int GetDoorState()
2178 return MoveDoor(DOOR_GET_STATE);
2181 unsigned int SetDoorState(unsigned int door_state)
2183 return MoveDoor(door_state | DOOR_SET_STATE);
2186 unsigned int MoveDoor(unsigned int door_state)
2188 static int door1 = DOOR_OPEN_1;
2189 static int door2 = DOOR_CLOSE_2;
2190 static unsigned long door_delay = 0;
2191 int x, start, stepsize = 2;
2192 unsigned long door_delay_value = stepsize * 5;
2194 if (door_state == DOOR_GET_STATE)
2195 return(door1 | door2);
2197 if (door_state & DOOR_SET_STATE)
2199 if (door_state & DOOR_ACTION_1)
2200 door1 = door_state & DOOR_ACTION_1;
2201 if (door_state & DOOR_ACTION_2)
2202 door2 = door_state & DOOR_ACTION_2;
2204 return(door1 | door2);
2207 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2208 door_state &= ~DOOR_OPEN_1;
2209 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2210 door_state &= ~DOOR_CLOSE_1;
2211 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2212 door_state &= ~DOOR_OPEN_2;
2213 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2214 door_state &= ~DOOR_CLOSE_2;
2216 if (setup.quick_doors)
2219 door_delay_value = 0;
2220 StopSound(SND_MENU_DOOR_OPENING);
2221 StopSound(SND_MENU_DOOR_CLOSING);
2224 if (door_state & DOOR_ACTION)
2226 if (!(door_state & DOOR_NO_DELAY))
2228 /* opening door sound has priority over simultaneously closing door */
2229 if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
2230 PlaySoundStereo(SND_MENU_DOOR_OPENING, SOUND_MAX_RIGHT);
2231 else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
2232 PlaySoundStereo(SND_MENU_DOOR_CLOSING, SOUND_MAX_RIGHT);
2235 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2237 for(x=start; x<=DXSIZE; x+=stepsize)
2239 Bitmap *bitmap = pix[PIX_DOOR];
2240 GC gc = bitmap->stored_clip_gc;
2242 WaitUntilDelayReached(&door_delay, door_delay_value);
2244 if (door_state & DOOR_ACTION_1)
2246 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
2247 int j = (DXSIZE - i) / 3;
2249 BlitBitmap(pix[PIX_DB_DOOR], drawto,
2250 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
2251 DXSIZE,DYSIZE - i/2, DX, DY);
2253 ClearRectangle(drawto, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
2255 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2256 BlitBitmapMasked(bitmap, drawto,
2257 DXSIZE, DOOR_GFX_PAGEY1, i, 77,
2258 DX + DXSIZE - i, DY + j);
2259 BlitBitmapMasked(bitmap, drawto,
2260 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
2261 DX + DXSIZE - i, DY + 140 + j);
2262 SetClipOrigin(bitmap, gc, DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
2263 BlitBitmapMasked(bitmap, drawto,
2264 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
2266 BlitBitmapMasked(bitmap, drawto,
2267 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
2270 BlitBitmapMasked(bitmap, drawto,
2271 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2273 BlitBitmapMasked(bitmap, drawto,
2274 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2276 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2277 BlitBitmapMasked(bitmap, drawto,
2278 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2279 DX + DXSIZE - i, DY + 77 + j);
2280 BlitBitmapMasked(bitmap, drawto,
2281 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2282 DX + DXSIZE - i, DY + 203 + j);
2284 redraw_mask |= REDRAW_DOOR_1;
2287 if (door_state & DOOR_ACTION_2)
2289 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
2290 int j = (VXSIZE - i) / 3;
2292 BlitBitmap(pix[PIX_DB_DOOR], drawto,
2293 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
2294 VXSIZE, VYSIZE - i/2, VX, VY);
2296 ClearRectangle(drawto, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
2298 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2299 BlitBitmapMasked(bitmap, drawto,
2300 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
2301 VX + VXSIZE-i, VY+j);
2302 SetClipOrigin(bitmap, gc,
2303 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2304 BlitBitmapMasked(bitmap, drawto,
2305 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
2308 BlitBitmapMasked(bitmap, drawto,
2309 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2310 i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
2311 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2312 BlitBitmapMasked(bitmap, drawto,
2313 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2315 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2317 redraw_mask |= REDRAW_DOOR_2;
2322 if (game_status == MAINMENU)
2327 if (setup.quick_doors)
2329 StopSound(SND_MENU_DOOR_OPENING);
2330 StopSound(SND_MENU_DOOR_CLOSING);
2333 if (door_state & DOOR_ACTION_1)
2334 door1 = door_state & DOOR_ACTION_1;
2335 if (door_state & DOOR_ACTION_2)
2336 door2 = door_state & DOOR_ACTION_2;
2338 return (door1 | door2);
2341 void DrawSpecialEditorDoor()
2343 /* draw bigger toolbox window */
2344 BlitBitmap(pix[PIX_DOOR], drawto,
2345 DOOR_GFX_PAGEX7, 0, 108, 56, EX - 4, EY - 12);
2347 redraw_mask |= REDRAW_ALL;
2350 void UndrawSpecialEditorDoor()
2352 /* draw normal tape recorder window */
2353 BlitBitmap(pix[PIX_BACK], drawto,
2354 562, 344, 108, 56, EX - 4, EY - 12);
2356 redraw_mask |= REDRAW_ALL;
2360 int ReadPixel(DrawBuffer *bitmap, int x, int y)
2362 XImage *pixel_image;
2363 unsigned long pixel_value;
2365 pixel_image = XGetImage(display, bitmap->drawable,
2366 x, y, 1, 1, AllPlanes, ZPixmap);
2367 pixel_value = XGetPixel(pixel_image, 0, 0);
2369 XDestroyImage(pixel_image);
2375 /* ---------- new tool button stuff ---------------------------------------- */
2377 /* graphic position values for tool buttons */
2378 #define TOOL_BUTTON_YES_XPOS 2
2379 #define TOOL_BUTTON_YES_YPOS 250
2380 #define TOOL_BUTTON_YES_GFX_YPOS 0
2381 #define TOOL_BUTTON_YES_XSIZE 46
2382 #define TOOL_BUTTON_YES_YSIZE 28
2383 #define TOOL_BUTTON_NO_XPOS 52
2384 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2385 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2386 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2387 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2388 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2389 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2390 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2391 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2392 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2393 #define TOOL_BUTTON_PLAYER_XSIZE 30
2394 #define TOOL_BUTTON_PLAYER_YSIZE 30
2395 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2396 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2397 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2398 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2399 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2400 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2401 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2402 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2403 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2404 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2405 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2406 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2407 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2408 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2409 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2410 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2411 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2412 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2413 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2414 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2423 } toolbutton_info[NUM_TOOL_BUTTONS] =
2426 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2427 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2428 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2433 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2434 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2435 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2440 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2441 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2442 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2443 TOOL_CTRL_ID_CONFIRM,
2447 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2448 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2449 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2450 TOOL_CTRL_ID_PLAYER_1,
2454 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2455 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2456 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2457 TOOL_CTRL_ID_PLAYER_2,
2461 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2462 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2463 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2464 TOOL_CTRL_ID_PLAYER_3,
2468 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2469 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2470 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2471 TOOL_CTRL_ID_PLAYER_4,
2476 void CreateToolButtons()
2480 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2482 Bitmap *gd_bitmap = pix[PIX_DOOR];
2483 Bitmap *deco_bitmap = None;
2484 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2485 struct GadgetInfo *gi;
2486 unsigned long event_mask;
2487 int gd_xoffset, gd_yoffset;
2488 int gd_x1, gd_x2, gd_y;
2491 event_mask = GD_EVENT_RELEASED;
2493 gd_xoffset = toolbutton_info[i].xpos;
2494 gd_yoffset = toolbutton_info[i].ypos;
2495 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2496 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2497 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2499 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2501 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
2503 getNewMiniGraphicSource(PLAYER_NR_GFX(IMG_PLAYER1, player_nr),
2504 &deco_bitmap, &deco_x, &deco_y);
2505 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2506 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2509 gi = CreateGadget(GDI_CUSTOM_ID, id,
2510 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2511 GDI_X, DX + toolbutton_info[i].x,
2512 GDI_Y, DY + toolbutton_info[i].y,
2513 GDI_WIDTH, toolbutton_info[i].width,
2514 GDI_HEIGHT, toolbutton_info[i].height,
2515 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2516 GDI_STATE, GD_BUTTON_UNPRESSED,
2517 GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
2518 GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
2519 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
2520 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2521 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2522 GDI_DECORATION_SHIFTING, 1, 1,
2523 GDI_EVENT_MASK, event_mask,
2524 GDI_CALLBACK_ACTION, HandleToolButtons,
2528 Error(ERR_EXIT, "cannot create gadget");
2530 tool_gadget[id] = gi;
2534 static void UnmapToolButtons()
2538 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2539 UnmapGadget(tool_gadget[i]);
2542 static void HandleToolButtons(struct GadgetInfo *gi)
2544 request_gadget_id = gi->custom_id;
2547 int get_next_element(int element)
2551 case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL;
2552 case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY;
2553 case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL;
2554 case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_ACTIVE;
2555 case EL_BD_MAGIC_WALL_FILLING: return EL_BD_MAGIC_WALL_FULL;
2556 case EL_BD_MAGIC_WALL_EMPTYING: return EL_BD_MAGIC_WALL_ACTIVE;
2557 case EL_AMOEBA_DRIPPING: return EL_AMOEBA_WET;
2559 default: return element;
2563 int el2gfx_OLD(int element)
2567 case EL_EMPTY: return -1;
2568 case EL_SAND: return GFX_ERDREICH;
2569 case EL_WALL: return GFX_MAUERWERK;
2570 case EL_WALL_CRUMBLED: return GFX_FELSBODEN;
2571 case EL_ROCK: return GFX_FELSBROCKEN;
2572 case EL_EMERALD: return GFX_EDELSTEIN;
2573 case EL_EXIT_CLOSED: return GFX_AUSGANG_ZU;
2574 case EL_EXIT_OPENING: return GFX_AUSGANG_ACT;
2575 case EL_EXIT_OPEN: return GFX_AUSGANG_AUF;
2576 case EL_SP_EXIT_OPEN: return GFX_SP_EXIT;
2577 case EL_PLAYER1: return GFX_SPIELER1;
2578 case EL_PLAYER2: return GFX_SPIELER2;
2579 case EL_PLAYER3: return GFX_SPIELER3;
2580 case EL_PLAYER4: return GFX_SPIELER4;
2581 case EL_BUG: return GFX_KAEFER;
2582 case EL_BUG_RIGHT: return GFX_KAEFER_RIGHT;
2583 case EL_BUG_UP: return GFX_KAEFER_UP;
2584 case EL_BUG_LEFT: return GFX_KAEFER_LEFT;
2585 case EL_BUG_DOWN: return GFX_KAEFER_DOWN;
2586 case EL_SPACESHIP: return GFX_FLIEGER;
2587 case EL_SPACESHIP_RIGHT: return GFX_FLIEGER_RIGHT;
2588 case EL_SPACESHIP_UP: return GFX_FLIEGER_UP;
2589 case EL_SPACESHIP_LEFT: return GFX_FLIEGER_LEFT;
2590 case EL_SPACESHIP_DOWN: return GFX_FLIEGER_DOWN;
2591 case EL_BD_BUTTERFLY: return GFX_BUTTERFLY;
2592 case EL_BD_BUTTERFLY_RIGHT: return GFX_BUTTERFLY_RIGHT;
2593 case EL_BD_BUTTERFLY_UP: return GFX_BUTTERFLY_UP;
2594 case EL_BD_BUTTERFLY_LEFT: return GFX_BUTTERFLY_LEFT;
2595 case EL_BD_BUTTERFLY_DOWN: return GFX_BUTTERFLY_DOWN;
2596 case EL_BD_FIREFLY: return GFX_FIREFLY;
2597 case EL_BD_FIREFLY_RIGHT: return GFX_FIREFLY_RIGHT;
2598 case EL_BD_FIREFLY_UP: return GFX_FIREFLY_UP;
2599 case EL_BD_FIREFLY_LEFT: return GFX_FIREFLY_LEFT;
2600 case EL_BD_FIREFLY_DOWN: return GFX_FIREFLY_DOWN;
2601 case EL_YAMYAM: return GFX_MAMPFER;
2602 case EL_ROBOT: return GFX_ROBOT;
2603 case EL_STEELWALL: return GFX_BETON;
2604 case EL_DIAMOND: return GFX_DIAMANT;
2605 case EL_QUICKSAND_EMPTY: return GFX_MORAST_LEER;
2606 case EL_QUICKSAND_FULL: return GFX_MORAST_VOLL;
2607 case EL_QUICKSAND_EMPTYING: return GFX_MORAST_LEER;
2608 case EL_AMOEBA_DROP: return GFX_TROPFEN;
2609 case EL_BOMB: return GFX_BOMBE;
2610 case EL_MAGIC_WALL: return GFX_MAGIC_WALL_OFF;
2611 case EL_MAGIC_WALL_ACTIVE: return GFX_MAGIC_WALL_EMPTY;
2612 case EL_MAGIC_WALL_EMPTYING: return GFX_MAGIC_WALL_EMPTY;
2613 case EL_MAGIC_WALL_FULL: return GFX_MAGIC_WALL_FULL;
2614 case EL_MAGIC_WALL_DEAD: return GFX_MAGIC_WALL_DEAD;
2615 case EL_ACID: return GFX_SALZSAEURE;
2616 case EL_AMOEBA_DEAD: return GFX_AMOEBE_TOT;
2617 case EL_AMOEBA_WET: return GFX_AMOEBE_NASS;
2618 case EL_AMOEBA_DRY: return GFX_AMOEBE_NORM;
2619 case EL_AMOEBA_FULL: return GFX_AMOEBE_VOLL;
2620 case EL_BD_AMOEBA: return GFX_AMOEBE_BD;
2621 case EL_AMOEBA_TO_DIAMOND: return GFX_AMOEBA2DIAM;
2622 case EL_AMOEBA_DRIPPING: return GFX_AMOEBE_NASS;
2623 case EL_NUT: return GFX_KOKOSNUSS;
2624 case EL_GAMEOFLIFE: return GFX_LIFE;
2625 case EL_BIOMAZE: return GFX_LIFE_ASYNC;
2626 case EL_DYNAMITE_ACTIVE: return GFX_DYNAMIT;
2627 case EL_STONEBLOCK: return GFX_BADEWANNE;
2628 case EL_ACIDPOOL_TOPLEFT: return GFX_BADEWANNE1;
2629 case EL_ACIDPOOL_TOPRIGHT: return GFX_BADEWANNE2;
2630 case EL_ACIDPOOL_BOTTOMLEFT: return GFX_BADEWANNE3;
2631 case EL_ACIDPOOL_BOTTOM: return GFX_BADEWANNE4;
2632 case EL_ACIDPOOL_BOTTOMRIGHT: return GFX_BADEWANNE5;
2633 case EL_ROBOT_WHEEL: return GFX_ABLENK_AUS;
2634 case EL_ROBOT_WHEEL_ACTIVE: return GFX_ABLENK_EIN;
2635 case EL_KEY1: return GFX_SCHLUESSEL1;
2636 case EL_KEY2: return GFX_SCHLUESSEL2;
2637 case EL_KEY3: return GFX_SCHLUESSEL3;
2638 case EL_KEY4: return GFX_SCHLUESSEL4;
2639 case EL_GATE1: return GFX_PFORTE1;
2640 case EL_GATE2: return GFX_PFORTE2;
2641 case EL_GATE3: return GFX_PFORTE3;
2642 case EL_GATE4: return GFX_PFORTE4;
2643 case EL_GATE1_GRAY: return GFX_PFORTE1X;
2644 case EL_GATE2_GRAY: return GFX_PFORTE2X;
2645 case EL_GATE3_GRAY: return GFX_PFORTE3X;
2646 case EL_GATE4_GRAY: return GFX_PFORTE4X;
2647 case EL_DYNAMITE: return GFX_DYNAMIT_AUS;
2648 case EL_PACMAN: return GFX_PACMAN;
2649 case EL_PACMAN_RIGHT: return GFX_PACMAN_RIGHT;
2650 case EL_PACMAN_UP: return GFX_PACMAN_UP;
2651 case EL_PACMAN_LEFT: return GFX_PACMAN_LEFT;
2652 case EL_PACMAN_DOWN: return GFX_PACMAN_DOWN;
2653 case EL_INVISIBLE_WALL: return GFX_UNSICHTBAR;
2654 case EL_INVISIBLE_WALL_ACTIVE: return GFX_UNSICHTBAR_ON;
2655 case EL_WALL_EMERALD: return GFX_ERZ_EDEL;
2656 case EL_WALL_DIAMOND: return GFX_ERZ_DIAM;
2657 case EL_LAMP: return GFX_BIRNE_AUS;
2658 case EL_LAMP_ACTIVE: return GFX_BIRNE_EIN;
2659 case EL_TIME_ORB_FULL: return GFX_ZEIT_VOLL;
2660 case EL_TIME_ORB_EMPTY: return GFX_ZEIT_LEER;
2661 case EL_WALL_GROWING: return GFX_MAUER_LEBT;
2662 case EL_WALL_GROWING_X: return GFX_MAUER_X;
2663 case EL_WALL_GROWING_Y: return GFX_MAUER_Y;
2664 case EL_WALL_GROWING_XY: return GFX_MAUER_XY;
2665 case EL_BD_DIAMOND: return GFX_EDELSTEIN_BD;
2666 case EL_EMERALD_YELLOW: return GFX_EDELSTEIN_GELB;
2667 case EL_EMERALD_RED: return GFX_EDELSTEIN_ROT;
2668 case EL_EMERALD_PURPLE: return GFX_EDELSTEIN_LILA;
2669 case EL_WALL_BD_DIAMOND: return GFX_ERZ_EDEL_BD;
2670 case EL_WALL_EMERALD_YELLOW: return GFX_ERZ_EDEL_GELB;
2671 case EL_WALL_EMERALD_RED: return GFX_ERZ_EDEL_ROT;
2672 case EL_WALL_EMERALD_PURPLE: return GFX_ERZ_EDEL_LILA;
2673 case EL_DARK_YAMYAM: return GFX_MAMPFER2;
2674 case EL_BD_MAGIC_WALL: return GFX_MAGIC_WALL_BD_OFF;
2675 case EL_BD_MAGIC_WALL_ACTIVE: return GFX_MAGIC_WALL_BD_EMPTY;
2676 case EL_BD_MAGIC_WALL_EMPTYING: return GFX_MAGIC_WALL_BD_EMPTY;
2677 case EL_BD_MAGIC_WALL_FULL: return GFX_MAGIC_WALL_BD_FULL;
2678 case EL_BD_MAGIC_WALL_DEAD: return GFX_MAGIC_WALL_BD_DEAD;
2679 case EL_DYNABOMB_PLAYER1_ACTIVE: return GFX_DYNABOMB;
2680 case EL_DYNABOMB_PLAYER2_ACTIVE: return GFX_DYNABOMB;
2681 case EL_DYNABOMB_PLAYER3_ACTIVE: return GFX_DYNABOMB;
2682 case EL_DYNABOMB_PLAYER4_ACTIVE: return GFX_DYNABOMB;
2683 case EL_DYNABOMB_NR: return GFX_DYNABOMB_NR;
2684 case EL_DYNABOMB_SZ: return GFX_DYNABOMB_SZ;
2685 case EL_DYNABOMB_XL: return GFX_DYNABOMB_XL;
2686 case EL_SOKOBAN_OBJECT: return GFX_SOKOBAN_OBJEKT;
2687 case EL_SOKOBAN_FIELD_EMPTY: return GFX_SOKOBAN_FELD_LEER;
2688 case EL_SOKOBAN_FIELD_FULL: return GFX_SOKOBAN_FELD_VOLL;
2689 case EL_MOLE: return GFX_MOLE;
2690 case EL_PENGUIN: return GFX_PINGUIN;
2691 case EL_PIG: return GFX_SCHWEIN;
2692 case EL_DRAGON: return GFX_DRACHE;
2693 case EL_SATELLITE: return GFX_SONDE;
2694 case EL_ARROW_BLUE_LEFT: return GFX_PFEIL_LEFT;
2695 case EL_ARROW_BLUE_RIGHT: return GFX_PFEIL_RIGHT;
2696 case EL_ARROW_BLUE_UP: return GFX_PFEIL_UP;
2697 case EL_ARROW_BLUE_DOWN: return GFX_PFEIL_DOWN;
2698 case EL_SPEED_PILL: return GFX_SPEED_PILL;
2699 case EL_SP_TERMINAL_ACTIVE: return GFX_SP_TERMINAL;
2700 case EL_SP_BUGGY_BASE_ACTIVE: return GFX_SP_BUG_ACTIVE;
2701 case EL_SP_ZONK: return GFX_SP_ZONK;
2702 /* ^^^^^^^^^^ non-standard position in supaplex graphic set! */
2703 case EL_INVISIBLE_STEELWALL: return GFX_INVISIBLE_STEEL;
2704 case EL_INVISIBLE_STEELWALL_ACTIVE: return GFX_INVISIBLE_STEEL_ON;
2705 case EL_BLACK_ORB: return GFX_BLACK_ORB;
2706 case EL_EM_GATE1: return GFX_EM_GATE_1;
2707 case EL_EM_GATE2: return GFX_EM_GATE_2;
2708 case EL_EM_GATE3: return GFX_EM_GATE_3;
2709 case EL_EM_GATE4: return GFX_EM_GATE_4;
2710 case EL_EM_GATE1_GRAY: return GFX_EM_GATE_1X;
2711 case EL_EM_GATE2_GRAY: return GFX_EM_GATE_2X;
2712 case EL_EM_GATE3_GRAY: return GFX_EM_GATE_3X;
2713 case EL_EM_GATE4_GRAY: return GFX_EM_GATE_4X;
2714 case EL_EM_KEY1_FILE: return GFX_EM_KEY_1;
2715 case EL_EM_KEY2_FILE: return GFX_EM_KEY_2;
2716 case EL_EM_KEY3_FILE: return GFX_EM_KEY_3;
2717 case EL_EM_KEY4_FILE: return GFX_EM_KEY_4;
2718 case EL_EM_KEY1: return GFX_EM_KEY_1;
2719 case EL_EM_KEY2: return GFX_EM_KEY_2;
2720 case EL_EM_KEY3: return GFX_EM_KEY_3;
2721 case EL_EM_KEY4: return GFX_EM_KEY_4;
2722 case EL_PEARL: return GFX_PEARL;
2723 case EL_CRYSTAL: return GFX_CRYSTAL;
2724 case EL_WALL_PEARL: return GFX_WALL_PEARL;
2725 case EL_WALL_CRYSTAL: return GFX_WALL_CRYSTAL;
2726 case EL_DOOR_WHITE: return GFX_DOOR_WHITE;
2727 case EL_DOOR_WHITE_GRAY: return GFX_DOOR_WHITE_GRAY;
2728 case EL_KEY_WHITE: return GFX_KEY_WHITE;
2729 case EL_SHIELD_NORMAL: return GFX_SHIELD_PASSIVE;
2730 case EL_SHIELD_DEADLY: return GFX_SHIELD_ACTIVE;
2731 case EL_EXTRA_TIME: return GFX_EXTRA_TIME;
2732 case EL_SWITCHGATE_OPEN: return GFX_SWITCHGATE_OPEN;
2733 case EL_SWITCHGATE_CLOSED: return GFX_SWITCHGATE_CLOSED;
2734 case EL_SWITCHGATE_SWITCH_UP: return GFX_SWITCHGATE_SWITCH_1;
2735 case EL_SWITCHGATE_SWITCH_DOWN: return GFX_SWITCHGATE_SWITCH_2;
2736 case EL_CONVEYOR_BELT1_LEFT: return GFX_BELT1_LEFT;
2737 case EL_CONVEYOR_BELT1_MIDDLE: return GFX_BELT1_MIDDLE;
2738 case EL_CONVEYOR_BELT1_RIGHT: return GFX_BELT1_RIGHT;
2739 case EL_CONVEYOR_BELT1_LEFT_ACTIVE: return GFX_BELT1_LEFT;
2740 case EL_CONVEYOR_BELT1_MIDDLE_ACTIVE:return GFX_BELT1_MIDDLE;
2741 case EL_CONVEYOR_BELT1_RIGHT_ACTIVE:return GFX_BELT1_RIGHT;
2742 case EL_CONVEYOR_BELT1_SWITCH_LEFT: return GFX_BELT1_SWITCH_LEFT;
2743 case EL_CONVEYOR_BELT1_SWITCH_MIDDLE:return GFX_BELT1_SWITCH_MIDDLE;
2744 case EL_CONVEYOR_BELT1_SWITCH_RIGHT:return GFX_BELT1_SWITCH_RIGHT;
2745 case EL_CONVEYOR_BELT2_LEFT: return GFX_BELT2_LEFT;
2746 case EL_CONVEYOR_BELT2_MIDDLE: return GFX_BELT2_MIDDLE;
2747 case EL_CONVEYOR_BELT2_RIGHT: return GFX_BELT2_RIGHT;
2748 case EL_CONVEYOR_BELT2_LEFT_ACTIVE: return GFX_BELT2_LEFT;
2749 case EL_CONVEYOR_BELT2_MIDDLE_ACTIVE:return GFX_BELT2_MIDDLE;
2750 case EL_CONVEYOR_BELT2_RIGHT_ACTIVE:return GFX_BELT2_RIGHT;
2751 case EL_CONVEYOR_BELT2_SWITCH_LEFT: return GFX_BELT2_SWITCH_LEFT;
2752 case EL_CONVEYOR_BELT2_SWITCH_MIDDLE:return GFX_BELT2_SWITCH_MIDDLE;
2753 case EL_CONVEYOR_BELT2_SWITCH_RIGHT:return GFX_BELT2_SWITCH_RIGHT;
2754 case EL_CONVEYOR_BELT3_LEFT: return GFX_BELT3_LEFT;
2755 case EL_CONVEYOR_BELT3_MIDDLE: return GFX_BELT3_MIDDLE;
2756 case EL_CONVEYOR_BELT3_RIGHT: return GFX_BELT3_RIGHT;
2757 case EL_CONVEYOR_BELT3_LEFT_ACTIVE: return GFX_BELT3_LEFT;
2758 case EL_CONVEYOR_BELT3_MIDDLE_ACTIVE:return GFX_BELT3_MIDDLE;
2759 case EL_CONVEYOR_BELT3_RIGHT_ACTIVE:return GFX_BELT3_RIGHT;
2760 case EL_CONVEYOR_BELT3_SWITCH_LEFT: return GFX_BELT3_SWITCH_LEFT;
2761 case EL_CONVEYOR_BELT3_SWITCH_MIDDLE:return GFX_BELT3_SWITCH_MIDDLE;
2762 case EL_CONVEYOR_BELT3_SWITCH_RIGHT:return GFX_BELT3_SWITCH_RIGHT;
2763 case EL_CONVEYOR_BELT4_LEFT: return GFX_BELT4_LEFT;
2764 case EL_CONVEYOR_BELT4_MIDDLE: return GFX_BELT4_MIDDLE;
2765 case EL_CONVEYOR_BELT4_RIGHT: return GFX_BELT4_RIGHT;
2766 case EL_CONVEYOR_BELT4_LEFT_ACTIVE: return GFX_BELT4_LEFT;
2767 case EL_CONVEYOR_BELT4_MIDDLE_ACTIVE:return GFX_BELT4_MIDDLE;
2768 case EL_CONVEYOR_BELT4_RIGHT_ACTIVE:return GFX_BELT4_RIGHT;
2769 case EL_CONVEYOR_BELT4_SWITCH_LEFT: return GFX_BELT4_SWITCH_LEFT;
2770 case EL_CONVEYOR_BELT4_SWITCH_MIDDLE:return GFX_BELT4_SWITCH_MIDDLE;
2771 case EL_CONVEYOR_BELT4_SWITCH_RIGHT:return GFX_BELT4_SWITCH_RIGHT;
2772 case EL_LANDMINE: return GFX_LANDMINE;
2773 case EL_ENVELOPE: return GFX_ENVELOPE;
2774 case EL_LIGHT_SWITCH: return GFX_LIGHT_SWITCH_OFF;
2775 case EL_LIGHT_SWITCH_ACTIVE: return GFX_LIGHT_SWITCH_ON;
2776 case EL_SIGN_EXCLAMATION: return GFX_SIGN_EXCLAMATION;
2777 case EL_SIGN_RADIOACTIVITY: return GFX_SIGN_RADIOACTIVITY;
2778 case EL_SIGN_STOP: return GFX_SIGN_STOP;
2779 case EL_SIGN_WHEELCHAIR: return GFX_SIGN_WHEELCHAIR;
2780 case EL_SIGN_PARKING: return GFX_SIGN_PARKING;
2781 case EL_SIGN_ONEWAY: return GFX_SIGN_ONEWAY;
2782 case EL_SIGN_HEART: return GFX_SIGN_HEART;
2783 case EL_SIGN_TRIANGLE: return GFX_SIGN_TRIANGLE;
2784 case EL_SIGN_ROUND: return GFX_SIGN_ROUND;
2785 case EL_SIGN_EXIT: return GFX_SIGN_EXIT;
2786 case EL_SIGN_YINYANG: return GFX_SIGN_YINYANG;
2787 case EL_SIGN_OTHER: return GFX_SIGN_OTHER;
2788 case EL_MOLE_LEFT: return GFX_MOLE_LEFT;
2789 case EL_MOLE_RIGHT: return GFX_MOLE_RIGHT;
2790 case EL_MOLE_UP: return GFX_MOLE_UP;
2791 case EL_MOLE_DOWN: return GFX_MOLE_DOWN;
2792 case EL_STEELWALL_SLANTED: return GFX_STEEL_SLANTED;
2793 case EL_INVISIBLE_SAND: return GFX_SAND_INVISIBLE;
2794 case EL_INVISIBLE_SAND_ACTIVE: return GFX_SAND_INVISIBLE_ON;
2795 case EL_DX_UNKNOWN_15: return GFX_DX_UNKNOWN_15;
2796 case EL_DX_UNKNOWN_42: return GFX_DX_UNKNOWN_42;
2797 case EL_TIMEGATE_OPEN: return GFX_TIMEGATE_OPEN;
2798 case EL_TIMEGATE_CLOSED: return GFX_TIMEGATE_CLOSED;
2799 case EL_TIMEGATE_SWITCH_ACTIVE: return GFX_TIMEGATE_SWITCH;
2800 case EL_TIMEGATE_SWITCH: return GFX_TIMEGATE_SWITCH;
2801 case EL_BALLOON: return GFX_BALLOON;
2802 case EL_BALLOON_SEND_LEFT: return GFX_BALLOON_SEND_LEFT;
2803 case EL_BALLOON_SEND_RIGHT: return GFX_BALLOON_SEND_RIGHT;
2804 case EL_BALLOON_SEND_UP: return GFX_BALLOON_SEND_UP;
2805 case EL_BALLOON_SEND_DOWN: return GFX_BALLOON_SEND_DOWN;
2806 case EL_BALLOON_SEND_ANY_DIRECTION: return GFX_BALLOON_SEND_ANY;
2807 case EL_EMC_STEELWALL1: return GFX_EMC_STEEL_WALL_1;
2808 case EL_EMC_STEELWALL2: return GFX_EMC_STEEL_WALL_2;
2809 case EL_EMC_STEELWALL3: return GFX_EMC_STEEL_WALL_3;
2810 case EL_EMC_STEELWALL4: return GFX_EMC_STEEL_WALL_4;
2811 case EL_EMC_WALL_PILLAR_UPPER: return GFX_EMC_WALL_1;
2812 case EL_EMC_WALL_PILLAR_MIDDLE: return GFX_EMC_WALL_2;
2813 case EL_EMC_WALL_PILLAR_LOWER: return GFX_EMC_WALL_3;
2814 case EL_EMC_WALL4: return GFX_EMC_WALL_4;
2815 case EL_EMC_WALL5: return GFX_EMC_WALL_5;
2816 case EL_EMC_WALL6: return GFX_EMC_WALL_6;
2817 case EL_EMC_WALL7: return GFX_EMC_WALL_7;
2818 case EL_EMC_WALL8: return GFX_EMC_WALL_8;
2819 case EL_TUBE_ALL: return GFX_TUBE_CROSS;
2820 case EL_TUBE_VERTICAL: return GFX_TUBE_VERTICAL;
2821 case EL_TUBE_HORIZONTAL: return GFX_TUBE_HORIZONTAL;
2822 case EL_TUBE_VERTICAL_LEFT: return GFX_TUBE_VERT_LEFT;
2823 case EL_TUBE_VERTICAL_RIGHT: return GFX_TUBE_VERT_RIGHT;
2824 case EL_TUBE_HORIZONTAL_UP: return GFX_TUBE_HORIZ_UP;
2825 case EL_TUBE_HORIZONTAL_DOWN: return GFX_TUBE_HORIZ_DOWN;
2826 case EL_TUBE_LEFT_UP: return GFX_TUBE_LEFT_UP;
2827 case EL_TUBE_LEFT_DOWN: return GFX_TUBE_LEFT_DOWN;
2828 case EL_TUBE_RIGHT_UP: return GFX_TUBE_RIGHT_UP;
2829 case EL_TUBE_RIGHT_DOWN: return GFX_TUBE_RIGHT_DOWN;
2830 case EL_SPRING: return GFX_SPRING;
2831 case EL_SPRING_MOVING: return GFX_SPRING;
2832 case EL_TRAP: return GFX_TRAP_INACTIVE;
2833 case EL_TRAP_ACTIVE: return GFX_TRAP_ACTIVE;
2834 case EL_BD_WALL: return GFX_BD_WALL;
2835 case EL_BD_ROCK: return GFX_BD_ROCK;
2836 case EL_DX_SUPABOMB: return GFX_DX_SUPABOMB;
2837 case EL_SP_MURPHY_CLONE: return GFX_SP_MURPHY_CLONE;
2841 if (IS_CHAR(element))
2842 return GFX_CHAR_START + (element - EL_CHAR_START);
2843 else if (element >= EL_SP_START && element <= EL_SP_END)
2845 int nr_element = element - EL_SP_START;
2846 int gfx_per_line = 8;
2848 (nr_element / gfx_per_line) * SP_PER_LINE +
2849 (nr_element % gfx_per_line);
2851 return GFX_START_ROCKSSP + nr_graphic;
2859 int el2gfx(int element)
2862 int graphic_OLD = el2gfx_OLD(element);
2867 int graphic_NEW = element_info[element].graphic[GFX_ACTION_DEFAULT];
2870 int graphic_OLD = el2gfx_OLD(element);
2872 if (element >= MAX_ELEMENTS)
2874 Error(ERR_WARN, "el2gfx: element == %d >= MAX_ELEMENTS", element);
2877 if (graphic_NEW != graphic_OLD)
2879 Error(ERR_WARN, "el2gfx: graphic_NEW (%d) != graphic_OLD (%d)",
2880 graphic_NEW, graphic_OLD);
2888 int el2img(int element)
2891 int graphic_NEW = element_info[element].graphic[GFX_ACTION_DEFAULT];
2894 if (graphic_NEW < 0)
2895 Error(ERR_WARN, "element %d -> graphic %d -- probably crashing now...",
2896 element, graphic_NEW);
2904 case EL_BD_BUTTERFLY: return IMG_BD_BUTTERFLY;
2905 case EL_BD_FIREFLY: return IMG_BD_FIREFLY;
2906 case EL_SP_ELECTRON: return IMG_SP_ELECTRON;
2916 int el_dir2img(int element, int direction)
2918 return el_dir_act2img(element, direction, GFX_ACTION_DEFAULT);
2921 int el_dir_act2img(int element, int direction, int action)
2923 action = graphics_action_mapping[action];
2924 direction = MV_DIR_BIT(direction);
2926 return element_info[element].direction_graphic[action][direction];