1 /***********************************************************
2 * Rocks'n'Diamonds -- McDuffin Strikes Back! *
3 *----------------------------------------------------------*
4 * (c) 1995-2002 Artsoft Entertainment *
6 * Detmolder Strasse 189 *
9 * e-mail: info@artsoft.org *
10 *----------------------------------------------------------*
12 ***********************************************************/
14 #include "libgame/libgame.h"
23 /* tool button identifiers */
24 #define TOOL_CTRL_ID_YES 0
25 #define TOOL_CTRL_ID_NO 1
26 #define TOOL_CTRL_ID_CONFIRM 2
27 #define TOOL_CTRL_ID_PLAYER_1 3
28 #define TOOL_CTRL_ID_PLAYER_2 4
29 #define TOOL_CTRL_ID_PLAYER_3 5
30 #define TOOL_CTRL_ID_PLAYER_4 6
32 #define NUM_TOOL_BUTTONS 7
34 /* forward declaration for internal use */
35 static void UnmapToolButtons();
36 static void HandleToolButtons(struct GadgetInfo *);
38 static struct GadgetInfo *tool_gadget[NUM_TOOL_BUTTONS];
39 static int request_gadget_id = -1;
41 void SetDrawtoField(int mode)
43 if (mode == DRAW_BUFFERED && setup.soft_scrolling)
54 drawto_field = fieldbuffer;
56 else /* DRAW_DIRECT, DRAW_BACKBUFFER */
67 drawto_field = (mode == DRAW_DIRECT ? window : backbuffer);
71 void RedrawPlayfield(boolean force_redraw, int x, int y, int width, int height)
73 if (game_status == PLAYING)
79 width = gfx.sxsize + 2 * TILEX;
80 height = gfx.sysize + 2 * TILEY;
83 if (force_redraw || setup.direct_draw)
86 int x1 = (x - SX) / TILEX, y1 = (y - SY) / TILEY;
87 int x2 = (x - SX + width) / TILEX, y2 = (y - SY + height) / TILEY;
89 if (setup.direct_draw)
90 SetDrawtoField(DRAW_BACKBUFFER);
92 for(xx=BX1; xx<=BX2; xx++)
93 for(yy=BY1; yy<=BY2; yy++)
94 if (xx >= x1 && xx <= x2 && yy >= y1 && yy <= y2)
95 DrawScreenField(xx, yy);
98 if (setup.direct_draw)
99 SetDrawtoField(DRAW_DIRECT);
102 if (setup.soft_scrolling)
104 int fx = FX, fy = FY;
106 fx += (ScreenMovDir & (MV_LEFT|MV_RIGHT) ? ScreenGfxPos : 0);
107 fy += (ScreenMovDir & (MV_UP|MV_DOWN) ? ScreenGfxPos : 0);
109 BlitBitmap(fieldbuffer, backbuffer, fx,fy, SXSIZE,SYSIZE, SX,SY);
113 BlitBitmap(drawto, window, x, y, width, height, x, y);
119 DrawBuffer *buffer = (drawto_field == window ? backbuffer : drawto_field);
121 if (setup.direct_draw && game_status == PLAYING)
122 redraw_mask &= ~REDRAW_MAIN;
124 if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD)
125 redraw_mask |= REDRAW_FIELD;
127 if (redraw_mask & REDRAW_FIELD)
128 redraw_mask &= ~REDRAW_TILES;
130 if (redraw_mask == REDRAW_NONE)
133 if (global.fps_slowdown && game_status == PLAYING)
135 static boolean last_frame_skipped = FALSE;
136 boolean skip_even_when_not_scrolling = TRUE;
137 boolean just_scrolling = (ScreenMovDir != 0);
138 boolean verbose = FALSE;
140 if (global.fps_slowdown_factor > 1 &&
141 (FrameCounter % global.fps_slowdown_factor) &&
142 (just_scrolling || skip_even_when_not_scrolling))
144 redraw_mask &= ~REDRAW_MAIN;
146 last_frame_skipped = TRUE;
149 printf("FRAME SKIPPED\n");
153 if (last_frame_skipped)
154 redraw_mask |= REDRAW_FIELD;
156 last_frame_skipped = FALSE;
159 printf("frame not skipped\n");
163 /* synchronize X11 graphics at this point; if we would synchronize the
164 display immediately after the buffer switching (after the XFlush),
165 this could mean that we have to wait for the graphics to complete,
166 although we could go on doing calculations for the next frame */
170 if (redraw_mask & REDRAW_ALL)
172 BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
176 if (redraw_mask & REDRAW_FIELD)
178 if (game_status != PLAYING || redraw_mask & REDRAW_FROM_BACKBUFFER)
180 BlitBitmap(backbuffer, window,
181 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE, REAL_SX, REAL_SY);
185 int fx = FX, fy = FY;
187 if (setup.soft_scrolling)
189 fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
190 fy += (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
193 if (setup.soft_scrolling ||
194 ABS(ScreenMovPos) + ScrollStepSize == TILEX ||
195 ABS(ScreenMovPos) == ScrollStepSize ||
196 redraw_tiles > REDRAWTILES_THRESHOLD)
198 BlitBitmap(buffer, window, fx, fy, SXSIZE, SYSIZE, SX, SY);
202 printf("redrawing all (ScreenGfxPos == %d) because %s\n",
204 (setup.soft_scrolling ?
205 "setup.soft_scrolling" :
206 ABS(ScreenGfxPos) + ScrollStepSize == TILEX ?
207 "ABS(ScreenGfxPos) + ScrollStepSize == TILEX" :
208 ABS(ScreenGfxPos) == ScrollStepSize ?
209 "ABS(ScreenGfxPos) == ScrollStepSize" :
210 "redraw_tiles > REDRAWTILES_THRESHOLD"));
216 redraw_mask &= ~REDRAW_MAIN;
219 if (redraw_mask & REDRAW_DOORS)
221 if (redraw_mask & REDRAW_DOOR_1)
222 BlitBitmap(backbuffer, window, DX, DY, DXSIZE, DYSIZE, DX, DY);
223 if (redraw_mask & REDRAW_DOOR_2)
225 if ((redraw_mask & REDRAW_DOOR_2) == REDRAW_DOOR_2)
226 BlitBitmap(backbuffer, window, VX,VY, VXSIZE,VYSIZE, VX,VY);
229 if (redraw_mask & REDRAW_VIDEO_1)
230 BlitBitmap(backbuffer, window,
231 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS,
232 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
233 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS);
234 if (redraw_mask & REDRAW_VIDEO_2)
235 BlitBitmap(backbuffer, window,
236 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS,
237 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
238 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS);
239 if (redraw_mask & REDRAW_VIDEO_3)
240 BlitBitmap(backbuffer, window,
241 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS,
242 VIDEO_CONTROL_XSIZE,VIDEO_CONTROL_YSIZE,
243 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS);
246 if (redraw_mask & REDRAW_DOOR_3)
247 BlitBitmap(backbuffer, window, EX, EY, EXSIZE, EYSIZE, EX, EY);
248 redraw_mask &= ~REDRAW_DOORS;
251 if (redraw_mask & REDRAW_MICROLEVEL)
253 BlitBitmap(backbuffer, window,
254 MICROLEV_XPOS, MICROLEV_YPOS, MICROLEV_XSIZE, MICROLEV_YSIZE,
255 MICROLEV_XPOS, MICROLEV_YPOS);
256 BlitBitmap(backbuffer, window,
257 SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE,
258 SX, MICROLABEL_YPOS);
259 redraw_mask &= ~REDRAW_MICROLEVEL;
262 if (redraw_mask & REDRAW_TILES)
264 for(x=0; x<SCR_FIELDX; x++)
265 for(y=0; y<SCR_FIELDY; y++)
266 if (redraw[redraw_x1 + x][redraw_y1 + y])
267 BlitBitmap(buffer, window,
268 FX + x * TILEX, FX + y * TILEY, TILEX, TILEY,
269 SX + x * TILEX, SY + y * TILEY);
272 if (redraw_mask & REDRAW_FPS) /* display frames per second */
277 sprintf(info1, " (only every %d. frame)", global.fps_slowdown_factor);
278 if (!global.fps_slowdown)
281 sprintf(text, "%.1f fps%s", global.frames_per_second, info1);
282 DrawTextExt(window, SX, SY, text, FS_SMALL, FC_YELLOW, FONT_OPAQUE);
287 for(x=0; x<MAX_BUF_XSIZE; x++)
288 for(y=0; y<MAX_BUF_YSIZE; y++)
291 redraw_mask = REDRAW_NONE;
297 long fading_delay = 300;
299 if (setup.fading && (redraw_mask & REDRAW_FIELD))
306 ClearRectangle(window, REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
309 for(i=0;i<2*FULL_SYSIZE;i++)
311 for(y=0;y<FULL_SYSIZE;y++)
313 BlitBitmap(backbuffer, window,
314 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
322 for(i=1;i<FULL_SYSIZE;i+=2)
323 BlitBitmap(backbuffer, window,
324 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
330 SetClipOrigin(clip_gc[PIX_FADEMASK], 0, 0);
331 BlitBitmapMasked(backbuffer, window,
332 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
337 SetClipOrigin(clip_gc[PIX_FADEMASK], -1, -1);
338 BlitBitmapMasked(backbuffer, window,
339 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
344 SetClipOrigin(clip_gc[PIX_FADEMASK], 0, -1);
345 BlitBitmapMasked(backbuffer, window,
346 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
351 SetClipOrigin(clip_gc[PIX_FADEMASK], -1, 0);
352 BlitBitmapMasked(backbuffer, window,
353 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
358 redraw_mask &= ~REDRAW_MAIN;
365 void SetMainBackgroundImage(int graphic)
367 SetMainBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
368 new_graphic_info[graphic].bitmap ?
369 new_graphic_info[graphic].bitmap :
370 new_graphic_info[IMG_BACKGROUND_DEFAULT].bitmap);
373 void SetDoorBackgroundImage(int graphic)
375 SetDoorBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
376 new_graphic_info[graphic].bitmap ?
377 new_graphic_info[graphic].bitmap :
378 new_graphic_info[IMG_BACKGROUND_DEFAULT].bitmap);
381 void DrawBackground(int dest_x, int dest_y, int width, int height)
383 ClearRectangleOnBackground(backbuffer, dest_x, dest_y, width, height);
385 redraw_mask |= REDRAW_FIELD;
390 DrawBackground(REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
392 if (setup.soft_scrolling && game_status == PLAYING)
394 ClearRectangle(fieldbuffer, 0, 0, FXSIZE, FYSIZE);
395 SetDrawtoField(DRAW_BUFFERED);
398 SetDrawtoField(DRAW_BACKBUFFER);
400 if (setup.direct_draw && game_status == PLAYING)
402 ClearRectangle(window, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
403 SetDrawtoField(DRAW_DIRECT);
407 void MarkTileDirty(int x, int y)
409 int xx = redraw_x1 + x;
410 int yy = redraw_y1 + y;
415 redraw[xx][yy] = TRUE;
416 redraw_mask |= REDRAW_TILES;
419 void SetBorderElement()
423 BorderElement = EL_EMPTY;
425 for(y=0; y<lev_fieldy && BorderElement == EL_EMPTY; y++)
427 for(x=0; x<lev_fieldx; x++)
429 if (!IS_MASSIVE(Feld[x][y]))
430 BorderElement = EL_STEELWALL;
432 if (y != 0 && y != lev_fieldy - 1 && x != lev_fieldx - 1)
438 static int getGraphicAnimationPhase(int frames, int delay, int mode)
442 if (mode & ANIM_PINGPONG)
444 int max_anim_frames = 2 * frames - 2;
446 phase = (FrameCounter % (delay * max_anim_frames)) / delay;
447 phase = (phase < frames ? phase : max_anim_frames - phase);
450 phase = (FrameCounter % (delay * frames)) / delay;
452 if (mode & ANIM_REVERSE)
458 inline int getGraphicAnimationFrame(int graphic, int sync_frame)
460 /* animation synchronized with global frame counter, not move position */
461 if (new_graphic_info[graphic].anim_global_sync || sync_frame < 0)
462 sync_frame = FrameCounter;
464 return getAnimationFrame(new_graphic_info[graphic].anim_frames,
465 new_graphic_info[graphic].anim_delay,
466 new_graphic_info[graphic].anim_mode,
467 new_graphic_info[graphic].anim_start_frame,
471 inline void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
472 int graphic, int sync_frame, int mask_mode)
474 int frame = getGraphicAnimationFrame(graphic, sync_frame);
476 if (mask_mode == USE_MASKING)
477 DrawGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
479 DrawGraphicExt(dst_bitmap, x, y, graphic, frame);
482 inline boolean DrawGraphicAnimation(int x, int y, int graphic)
484 int lx = LEVELX(x), ly = LEVELY(y);
486 if (!IN_SCR_FIELD(x, y) ||
487 (GfxFrame[lx][ly] % new_graphic_info[graphic].anim_delay) != 0)
490 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
491 graphic, GfxFrame[lx][ly], NO_MASKING);
497 boolean DrawLevelGraphicAnimation(int x, int y, int graphic)
499 return DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
502 boolean DrawLevelElementAnimation(int x, int y, int element)
504 return DrawGraphicAnimation(SCREENX(x), SCREENY(y), el2img(element));
507 void DrawAllPlayers()
511 for(i=0; i<MAX_PLAYERS; i++)
512 if (stored_player[i].active)
513 DrawPlayer(&stored_player[i]);
516 void DrawPlayerField(int x, int y)
518 if (!IS_PLAYER(x, y))
521 DrawPlayer(PLAYERINFO(x, y));
524 void DrawPlayer(struct PlayerInfo *player)
526 int jx = player->jx, jy = player->jy;
527 int last_jx = player->last_jx, last_jy = player->last_jy;
528 int next_jx = jx + (jx - last_jx), next_jy = jy + (jy - last_jy);
529 int sx = SCREENX(jx), sy = SCREENY(jy);
530 int sxx = 0, syy = 0;
531 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
534 boolean player_is_moving = (last_jx != jx || last_jy != jy ? TRUE : FALSE);
536 if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
540 if (!IN_LEV_FIELD(jx,jy))
542 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
543 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
544 printf("DrawPlayerField(): This should never happen!\n");
549 if (element == EL_EXPLOSION)
552 /* draw things in the field the player is leaving, if needed */
554 if (player_is_moving)
556 if (Store[last_jx][last_jy] && IS_DRAWABLE(last_element))
558 DrawLevelElement(last_jx, last_jy, Store[last_jx][last_jy]);
560 if (last_element == EL_DYNAMITE_ACTIVE)
561 DrawDynamite(last_jx, last_jy);
563 DrawLevelFieldThruMask(last_jx, last_jy);
565 else if (last_element == EL_DYNAMITE_ACTIVE)
566 DrawDynamite(last_jx, last_jy);
568 DrawLevelField(last_jx, last_jy);
570 if (player->Pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
574 if (Feld[next_jx][next_jy] == EL_SOKOBAN_FIELD_FULL)
575 DrawLevelElement(next_jx, next_jy, EL_SOKOBAN_FIELD_EMPTY);
577 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
580 DrawLevelField(next_jx, next_jy);
584 if (!IN_SCR_FIELD(sx, sy))
587 if (setup.direct_draw)
588 SetDrawtoField(DRAW_BUFFERED);
590 /* draw things behind the player, if needed */
593 DrawLevelElement(jx, jy, Store[jx][jy]);
594 else if (!IS_ACTIVE_BOMB(element))
595 DrawLevelField(jx, jy);
597 DrawLevelElement(jx, jy, EL_EMPTY);
599 /* draw player himself */
601 if (game.emulation == EMU_SUPAPLEX)
603 static int last_dir = MV_LEFT;
604 int action = (player->programmed_action ? player->programmed_action :
606 boolean action_moving =
608 ((action & (MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN)) &&
609 !(action & ~(MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN))));
611 graphic = IMG_SP_MURPHY;
615 if (player->MovDir == MV_LEFT)
616 graphic = IMG_SP_MURPHY_LEFT_PUSHING;
617 else if (player->MovDir == MV_RIGHT)
618 graphic = IMG_SP_MURPHY_RIGHT_PUSHING;
619 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
620 graphic = IMG_SP_MURPHY_LEFT_PUSHING;
621 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
622 graphic = IMG_SP_MURPHY_RIGHT_PUSHING;
624 else if (player->snapped)
626 if (player->MovDir == MV_LEFT)
627 graphic = IMG_SP_MURPHY_LEFT_SNAPPING;
628 else if (player->MovDir == MV_RIGHT)
629 graphic = IMG_SP_MURPHY_RIGHT_SNAPPING;
630 else if (player->MovDir == MV_UP)
631 graphic = IMG_SP_MURPHY_UP_SNAPPING;
632 else if (player->MovDir == MV_DOWN)
633 graphic = IMG_SP_MURPHY_DOWN_SNAPPING;
635 else if (action_moving)
637 if (player->MovDir == MV_LEFT)
638 graphic = IMG_SP_MURPHY_LEFT_MOVING;
639 else if (player->MovDir == MV_RIGHT)
640 graphic = IMG_SP_MURPHY_RIGHT_MOVING;
641 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
642 graphic = IMG_SP_MURPHY_LEFT_MOVING;
643 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
644 graphic = IMG_SP_MURPHY_RIGHT_MOVING;
646 graphic = IMG_SP_MURPHY_LEFT_MOVING;
648 frame = getGraphicAnimationFrame(graphic, -1);
651 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
652 last_dir = player->MovDir;
656 if (player->MovDir == MV_LEFT)
657 graphic = (player->Pushing ? IMG_PLAYER1_LEFT_PUSHING :
658 player->is_moving ? IMG_PLAYER1_LEFT_MOVING :
660 else if (player->MovDir == MV_RIGHT)
661 graphic = (player->Pushing ? IMG_PLAYER1_RIGHT_PUSHING :
662 player->is_moving ? IMG_PLAYER1_RIGHT_MOVING :
664 else if (player->MovDir == MV_UP)
665 graphic = (player->Pushing ? IMG_PLAYER1_UP_PUSHING :
666 player->is_moving ? IMG_PLAYER1_UP_MOVING :
668 else /* MV_DOWN || MV_NO_MOVING */
669 graphic = (player->Pushing ? IMG_PLAYER1_DOWN_PUSHING :
670 player->is_moving ? IMG_PLAYER1_DOWN_MOVING :
673 graphic = PLAYER_NR_GFX(graphic, player->index_nr);
676 frame = player->Frame;
678 frame = getGraphicAnimationFrame(graphic, player->Frame);
684 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
685 sxx = player->GfxPos;
687 syy = player->GfxPos;
690 if (!setup.soft_scrolling && ScreenMovPos)
695 printf("-> %d\n", player->Frame);
698 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
700 if (SHIELD_ON(player))
702 int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
703 IMG_SHIELD_NORMAL_ACTIVE);
704 int frame = getGraphicAnimationFrame(graphic, -1);
706 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
710 if (player->Pushing && player->GfxPos)
712 if (player->Pushing && player_is_moving)
715 int px = SCREENX(next_jx), py = SCREENY(next_jy);
718 (element == EL_SOKOBAN_FIELD_EMPTY ||
719 Feld[next_jx][next_jy] == EL_SOKOBAN_FIELD_FULL))
720 DrawGraphicShiftedThruMask(px, py, sxx, syy, IMG_SOKOBAN_OBJECT, 0,
724 int element = Feld[next_jx][next_jy];
725 int graphic = el2img(element);
730 if ((sxx || syy) && IS_PUSHABLE(element))
732 graphic = el_dir_act2img(element, player->MovDir, GFX_ACTION_MOVING);
734 frame = getGraphicAnimationFrame(graphic, player->GfxPos);
736 frame = getGraphicAnimationFrame(graphic, player->Frame);
740 printf("-> %d [%d]\n", player->Frame, player->GfxPos);
745 if (player->MovDir == MV_LEFT)
750 frame = (player->GfxPos / (TILEX / 4));
752 if (player->MovDir == MV_RIGHT)
753 frame = (frame + 4) % 4;
757 DrawGraphicShifted(px, py, sxx, syy, graphic, frame,
758 NO_CUTTING, NO_MASKING);
762 /* draw things in front of player (active dynamite or dynabombs) */
764 if (IS_ACTIVE_BOMB(element))
766 graphic = el2img(element);
769 if (element == EL_DYNAMITE_ACTIVE)
771 if ((frame = (96 - MovDelay[jx][jy]) / 12) > 6)
776 if ((frame = ((96 - MovDelay[jx][jy]) / 6) % 8) > 3)
780 frame = getGraphicAnimationFrame(graphic, 96 - MovDelay[jx][jy]);
783 if (game.emulation == EMU_SUPAPLEX)
784 DrawGraphic(sx, sy, IMG_SP_DISK_RED, 0);
786 DrawGraphicThruMask(sx, sy, graphic, frame);
789 if (player_is_moving && last_element == EL_EXPLOSION)
791 int stored = Store[last_jx][last_jy];
792 int graphic = (game.emulation != EMU_SUPAPLEX ? IMG_EXPLOSION :
793 stored == EL_SP_INFOTRON ? IMG_SP_EXPLOSION_INFOTRON :
795 int delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2);
796 int phase = ExplodePhase[last_jx][last_jy] - 1;
797 int frame = getGraphicAnimationFrame(graphic, phase - delay);
800 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy), graphic, frame);
803 /* draw elements that stay over the player */
804 /* handle the field the player is leaving ... */
805 if (player_is_moving && IS_OVER_PLAYER(last_element))
806 DrawLevelField(last_jx, last_jy);
808 /* ... and the field the player is entering */
809 if (IS_OVER_PLAYER(element))
810 DrawLevelField(jx, jy);
812 if (setup.direct_draw)
814 int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
815 int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
816 int x_size = TILEX * (1 + ABS(jx - last_jx));
817 int y_size = TILEY * (1 + ABS(jy - last_jy));
819 BlitBitmap(drawto_field, window,
820 dest_x, dest_y, x_size, y_size, dest_x, dest_y);
821 SetDrawtoField(DRAW_DIRECT);
824 MarkTileDirty(sx,sy);
828 void getOldGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
830 if (graphic >= 0 && graphic_info[graphic].bitmap != NULL)
832 *bitmap = graphic_info[graphic].bitmap;
833 *x = graphic_info[graphic].src_x;
834 *y = graphic_info[graphic].src_y;
836 else if (graphic >= GFX_START_ROCKSELEMENTS &&
837 graphic <= GFX_END_ROCKSELEMENTS)
839 graphic -= GFX_START_ROCKSELEMENTS;
840 *bitmap = new_graphic_info[IMG_OLD_PIX_ELEMENTS].bitmap;
841 *x = (graphic % GFX_PER_LINE) * TILEX;
842 *y = (graphic / GFX_PER_LINE) * TILEY;
844 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
846 graphic -= GFX_START_ROCKSHEROES;
847 *bitmap = new_graphic_info[IMG_OLD_PIX_HEROES].bitmap;
848 *x = (graphic % HEROES_PER_LINE) * TILEX;
849 *y = (graphic / HEROES_PER_LINE) * TILEY;
851 else if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
853 graphic -= GFX_START_ROCKSSP;
854 *bitmap = new_graphic_info[IMG_OLD_PIX_SP].bitmap;
855 *x = (graphic % SP_PER_LINE) * TILEX;
856 *y = (graphic / SP_PER_LINE) * TILEY;
858 else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
860 graphic -= GFX_START_ROCKSDC;
861 *bitmap = new_graphic_info[IMG_OLD_PIX_DC].bitmap;
862 *x = (graphic % DC_PER_LINE) * TILEX;
863 *y = (graphic / DC_PER_LINE) * TILEY;
865 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
867 graphic -= GFX_START_ROCKSMORE;
868 *bitmap = new_graphic_info[IMG_OLD_PIX_MORE].bitmap;
869 *x = (graphic % MORE_PER_LINE) * TILEX;
870 *y = (graphic / MORE_PER_LINE) * TILEY;
872 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
874 graphic -= GFX_START_ROCKSFONT;
875 *bitmap = new_graphic_info[IMG_OLD_PIX_FONT_EM].bitmap;
876 *x = (graphic % FONT_CHARS_PER_LINE) * TILEX;
877 *y = (graphic / FONT_CHARS_PER_LINE) * TILEY;
881 *bitmap = new_graphic_info[IMG_OLD_PIX_SP].bitmap;
888 void getGraphicSource(int graphic, int frame, Bitmap **bitmap, int *x, int *y)
890 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
891 int offset_x = new_graphic_info[graphic].offset_x;
892 int offset_y = new_graphic_info[graphic].offset_y;
893 int src_x = new_graphic_info[graphic].src_x + frame * offset_x;
894 int src_y = new_graphic_info[graphic].src_y + frame * offset_y;
896 *bitmap = src_bitmap;
901 void DrawGraphic(int x, int y, int graphic, int frame)
904 if (!IN_SCR_FIELD(x, y))
906 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
907 printf("DrawGraphic(): This should never happen!\n");
912 DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic, frame);
917 void DrawOldGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic)
922 getOldGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
923 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
927 void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
934 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
936 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
937 int src_x = new_graphic_info[graphic].src_x;
938 int src_y = new_graphic_info[graphic].src_y;
939 int offset_x = new_graphic_info[graphic].offset_x;
940 int offset_y = new_graphic_info[graphic].offset_y;
942 src_x += frame * offset_x;
943 src_y += frame * offset_y;
946 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
949 void DrawGraphicThruMask(int x, int y, int graphic, int frame)
952 if (!IN_SCR_FIELD(x, y))
954 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
955 printf("DrawGraphicThruMask(): This should never happen!\n");
960 DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY, graphic,
965 void DrawGraphicThruMaskExt(DrawBuffer *d, int dest_x, int dest_y, int graphic,
973 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
974 drawing_gc = src_bitmap->stored_clip_gc;
976 GC drawing_gc = src_bitmap->stored_clip_gc;
977 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
978 int src_x = new_graphic_info[graphic].src_x;
979 int src_y = new_graphic_info[graphic].src_y;
980 int offset_x = new_graphic_info[graphic].offset_x;
981 int offset_y = new_graphic_info[graphic].offset_y;
983 src_x += frame * offset_x;
984 src_y += frame * offset_y;
988 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
989 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dest_x, dest_y);
992 void DrawMiniGraphic(int x, int y, int graphic)
994 DrawMiniGraphicExt(drawto, SX + x * MINI_TILEX,SY + y * MINI_TILEY, graphic);
995 MarkTileDirty(x / 2, y / 2);
998 void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1000 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
1001 int mini_startx = 0;
1002 int mini_starty = src_bitmap->height * 2 / 3;
1003 int src_x = mini_startx + new_graphic_info[graphic].src_x / 2;
1004 int src_y = mini_starty + new_graphic_info[graphic].src_y / 2;
1006 if (src_x + MINI_TILEX > src_bitmap->width ||
1007 src_y + MINI_TILEY > src_bitmap->height)
1009 /* graphic of desired size seems not to be contained in this image;
1010 dirty workaround: get it from the middle of the normal sized image */
1012 getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
1013 src_x += (TILEX / 2 - MINI_TILEX / 2);
1014 src_y += (TILEY / 2 - MINI_TILEY / 2);
1017 *bitmap = src_bitmap;
1022 void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
1027 getMiniGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1028 BlitBitmap(src_bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
1031 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic, int frame,
1032 int cut_mode, int mask_mode)
1041 int width = TILEX, height = TILEY;
1047 DrawGraphic(x, y, graphic, frame);
1051 if (dx || dy) /* shifted graphic */
1053 if (x < BX1) /* object enters playfield from the left */
1060 else if (x > BX2) /* object enters playfield from the right */
1066 else if (x==BX1 && dx < 0) /* object leaves playfield to the left */
1072 else if (x==BX2 && dx > 0) /* object leaves playfield to the right */
1074 else if (dx) /* general horizontal movement */
1075 MarkTileDirty(x + SIGN(dx), y);
1077 if (y < BY1) /* object enters playfield from the top */
1079 if (cut_mode==CUT_BELOW) /* object completely above top border */
1087 else if (y > BY2) /* object enters playfield from the bottom */
1093 else if (y==BY1 && dy < 0) /* object leaves playfield to the top */
1099 else if (dy > 0 && cut_mode == CUT_ABOVE)
1101 if (y == BY2) /* object completely above bottom border */
1107 MarkTileDirty(x, y + 1);
1108 } /* object leaves playfield to the bottom */
1109 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1111 else if (dy) /* general vertical movement */
1112 MarkTileDirty(x, y + SIGN(dy));
1115 src_bitmap = new_graphic_info[graphic].bitmap;
1116 src_x = new_graphic_info[graphic].src_x;
1117 src_y = new_graphic_info[graphic].src_y;
1118 offset_x = new_graphic_info[graphic].offset_x;
1119 offset_y = new_graphic_info[graphic].offset_y;
1121 drawing_gc = src_bitmap->stored_clip_gc;
1123 src_x += frame * offset_x;
1124 src_y += frame * offset_y;
1129 dest_x = FX + x * TILEX + dx;
1130 dest_y = FY + y * TILEY + dy;
1133 if (!IN_SCR_FIELD(x,y))
1135 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1136 printf("DrawGraphicShifted(): This should never happen!\n");
1141 if (mask_mode == USE_MASKING)
1143 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1144 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
1148 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1154 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
1155 int frame, int cut_mode)
1157 DrawGraphicShifted(x,y, dx,dy, graphic, frame, cut_mode, USE_MASKING);
1161 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1162 int cut_mode, int mask_mode)
1164 int ux = LEVELX(x), uy = LEVELY(y);
1165 int graphic = el2gfx(element);
1166 int phase8 = ABS(MovPos[ux][uy]) / (TILEX / 8);
1167 int phase4 = phase8 / 2;
1168 int phase2 = phase8 / 4;
1169 int dir = MovDir[ux][uy];
1171 if (element == EL_PACMAN || element == EL_BUG || element == EL_SPACESHIP)
1173 graphic += 1 * !phase2;
1177 else if (dir == MV_LEFT)
1179 else if (dir == MV_DOWN)
1182 else if (element == EL_SP_SNIKSNAK)
1185 graphic = GFX_SP_SNIKSNAK_LEFT;
1186 else if (dir == MV_RIGHT)
1187 graphic = GFX_SP_SNIKSNAK_RIGHT;
1188 else if (dir == MV_UP)
1189 graphic = GFX_SP_SNIKSNAK_UP;
1191 graphic = GFX_SP_SNIKSNAK_DOWN;
1193 graphic += (phase8 < 4 ? phase8 : 7 - phase8);
1195 else if (element == EL_SP_ELECTRON)
1197 graphic = GFX2_SP_ELECTRON + getGraphicAnimationPhase(8, 2, ANIM_LOOP);
1199 else if (element == EL_MOLE || element == EL_PENGUIN ||
1200 element == EL_PIG || element == EL_DRAGON)
1203 graphic = (element == EL_MOLE ? GFX_MOLE_LEFT :
1204 element == EL_PENGUIN ? GFX_PINGUIN_LEFT :
1205 element == EL_PIG ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
1206 else if (dir == MV_RIGHT)
1207 graphic = (element == EL_MOLE ? GFX_MOLE_RIGHT :
1208 element == EL_PENGUIN ? GFX_PINGUIN_RIGHT :
1209 element == EL_PIG ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
1210 else if (dir == MV_UP)
1211 graphic = (element == EL_MOLE ? GFX_MOLE_UP :
1212 element == EL_PENGUIN ? GFX_PINGUIN_UP :
1213 element == EL_PIG ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
1215 graphic = (element == EL_MOLE ? GFX_MOLE_DOWN :
1216 element == EL_PENGUIN ? GFX_PINGUIN_DOWN :
1217 element == EL_PIG ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
1221 else if (element == EL_SATELLITE)
1223 graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_LOOP);
1225 else if (element == EL_ACID)
1227 graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_LOOP);
1229 else if (element == EL_BD_BUTTERFLY || element == EL_BD_FIREFLY)
1233 else if (element == EL_BALLOON)
1237 else if ((element == EL_ROCK ||
1238 element == EL_SP_ZONK ||
1239 element == EL_BD_ROCK ||
1240 element == EL_SP_INFOTRON ||
1244 if (uy >= lev_fieldy-1 || !IS_BELT(Feld[ux][uy+1]))
1246 if (element == EL_ROCK ||
1247 element == EL_SP_ZONK ||
1248 element == EL_BD_ROCK)
1251 graphic += (4 - phase4) % 4;
1252 else if (dir == MV_RIGHT)
1255 graphic += phase2 * 2;
1257 else if (element != EL_SP_INFOTRON)
1261 else if (element == EL_MAGIC_WALL_ACTIVE ||
1262 element == EL_MAGIC_WALL_EMPTYING ||
1263 element == EL_BD_MAGIC_WALL_ACTIVE ||
1264 element == EL_BD_MAGIC_WALL_EMPTYING ||
1265 element == EL_MAGIC_WALL_FULL ||
1266 element == EL_BD_MAGIC_WALL_FULL)
1268 graphic += 3 + getGraphicAnimationPhase(4, 4, ANIM_REVERSE);
1270 else if (IS_AMOEBOID(element) || element == EL_AMOEBA_DRIPPING)
1272 graphic = (element == EL_AMOEBA_DEAD ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
1273 graphic += (x + 2 * y + 4) % 4;
1275 else if (element == EL_WALL_GROWING)
1277 boolean links_massiv = FALSE, rechts_massiv = FALSE;
1279 if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
1280 links_massiv = TRUE;
1281 if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
1282 rechts_massiv = TRUE;
1284 if (links_massiv && rechts_massiv)
1285 graphic = GFX_MAUERWERK;
1286 else if (links_massiv)
1287 graphic = GFX_MAUER_R;
1288 else if (rechts_massiv)
1289 graphic = GFX_MAUER_L;
1292 else if ((element == EL_INVISIBLE_STEELWALL ||
1293 element == EL_INVISIBLE_WALL ||
1294 element == EL_INVISIBLE_SAND) && game.light_time_left)
1296 graphic = (element == EL_INVISIBLE_STEELWALL ? GFX_INVISIBLE_STEEL_ON :
1297 element == EL_INVISIBLE_WALL ? GFX_UNSICHTBAR_ON :
1298 GFX_SAND_INVISIBLE_ON);
1303 DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
1304 else if (mask_mode == USE_MASKING)
1305 DrawGraphicThruMask(x, y, graphic);
1307 DrawGraphic(x, y, graphic);
1311 inline static int getFramePosition(int x, int y)
1313 int frame_pos = -1; /* default: global synchronization */
1315 int element = Feld[x][y];
1317 if (element == EL_QUICKSAND_FULL ||
1318 element == EL_MAGIC_WALL_FULL ||
1319 element == EL_BD_MAGIC_WALL_FULL)
1321 else if (IS_MOVING(x, y) || CAN_MOVE(element) || CAN_FALL(element))
1322 frame_pos = ABS(MovPos[x][y]) / (TILEX / 8);
1325 frame_pos = ABS(MovPos[x][y]) / (TILEX / 8);
1327 frame_pos = GfxFrame[x][y];
1334 inline static int getGfxAction(int x, int y)
1336 int gfx_action = GFX_ACTION_DEFAULT;
1339 if (GfxAction[x][y] != GFX_ACTION_DEFAULT)
1340 gfx_action = GfxAction[x][y];
1341 else if (IS_MOVING(x, y))
1342 gfx_action = GFX_ACTION_MOVING;
1344 gfx_action = GfxAction[x][y];
1349 printf("getGfxAction: THIS SHOULD NEVER HAPPEN: GfxAction[%d][%d] == %d\n",
1356 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1357 int cut_mode, int mask_mode)
1359 int ux = LEVELX(x), uy = LEVELY(y);
1363 if (IN_LEV_FIELD(ux, uy))
1365 int move_dir = MovDir[ux][uy];
1366 int move_pos = getFramePosition(ux, uy);
1367 int gfx_action = getGfxAction(ux, uy);
1369 graphic = el_dir_act2img(element, move_dir, gfx_action);
1370 frame = getGraphicAnimationFrame(graphic, move_pos);
1374 graphic = el2img(element);
1375 frame = getGraphicAnimationFrame(graphic, 0);
1378 if (element == EL_WALL_GROWING)
1380 boolean left_stopped = FALSE, right_stopped = FALSE;
1382 if (!IN_LEV_FIELD(ux - 1, uy) || IS_MAUER(Feld[ux - 1][uy]))
1383 left_stopped = TRUE;
1384 if (!IN_LEV_FIELD(ux + 1, uy) || IS_MAUER(Feld[ux + 1][uy]))
1385 right_stopped = TRUE;
1387 if (left_stopped && right_stopped)
1389 else if (left_stopped)
1391 graphic = IMG_WALL_GROWING_ACTIVE_RIGHT;
1392 frame = new_graphic_info[graphic].anim_frames - 1;
1394 else if (right_stopped)
1396 graphic = IMG_WALL_GROWING_ACTIVE_LEFT;
1397 frame = new_graphic_info[graphic].anim_frames - 1;
1400 else if (IS_AMOEBOID(element) || element == EL_AMOEBA_DRIPPING)
1402 graphic = (element == EL_BD_AMOEBA ? IMG_BD_AMOEBA_PART1 :
1403 element == EL_AMOEBA_WET ? IMG_AMOEBA_WET_PART1 :
1404 element == EL_AMOEBA_DRY ? IMG_AMOEBA_DRY_PART1 :
1405 element == EL_AMOEBA_FULL ? IMG_AMOEBA_FULL_PART1 :
1406 IMG_AMOEBA_DEAD_PART1);
1408 graphic += (x + 2 * y + 4) % 4;
1412 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
1413 else if (mask_mode == USE_MASKING)
1414 DrawGraphicThruMask(x, y, graphic, frame);
1416 DrawGraphic(x, y, graphic, frame);
1419 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1420 int cut_mode, int mask_mode)
1422 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1423 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1424 cut_mode, mask_mode);
1427 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1430 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1433 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1436 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1440 void DrawOldScreenElementThruMask(int x, int y, int element)
1442 DrawOldScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1445 void DrawScreenElementThruMask(int x, int y, int element)
1447 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1451 void DrawLevelElementThruMask(int x, int y, int element)
1453 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1456 void DrawLevelFieldThruMask(int x, int y)
1458 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1461 void DrawCrumbledSand(int x, int y)
1465 int i, width, height, cx,cy;
1466 int ux = LEVELX(x), uy = LEVELY(y);
1467 int element, graphic;
1469 static int xy[4][2] =
1477 if (!IN_LEV_FIELD(ux, uy))
1480 element = Feld[ux][uy];
1482 if (element == EL_SAND ||
1483 element == EL_LANDMINE ||
1484 element == EL_TRAP ||
1485 element == EL_TRAP_ACTIVE)
1487 if (!IN_SCR_FIELD(x, y))
1490 graphic = IMG_SAND_CRUMBLED;
1492 src_bitmap = new_graphic_info[graphic].bitmap;
1493 src_x = new_graphic_info[graphic].src_x;
1494 src_y = new_graphic_info[graphic].src_y;
1500 uxx = ux + xy[i][0];
1501 uyy = uy + xy[i][1];
1502 if (!IN_LEV_FIELD(uxx, uyy))
1503 element = EL_STEELWALL;
1505 element = Feld[uxx][uyy];
1507 if (element == EL_SAND ||
1508 element == EL_LANDMINE ||
1509 element == EL_TRAP ||
1510 element == EL_TRAP_ACTIVE)
1513 if (i == 1 || i == 2)
1517 cx = (i == 2 ? TILEX - snip : 0);
1525 cy = (i == 3 ? TILEY - snip : 0);
1528 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1529 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1532 MarkTileDirty(x, y);
1536 graphic = IMG_SAND_CRUMBLED;
1538 src_bitmap = new_graphic_info[graphic].bitmap;
1539 src_x = new_graphic_info[graphic].src_x;
1540 src_y = new_graphic_info[graphic].src_y;
1544 int xx, yy, uxx, uyy;
1548 uxx = ux + xy[i][0];
1549 uyy = uy + xy[i][1];
1551 if (!IN_LEV_FIELD(uxx, uyy) ||
1552 (Feld[uxx][uyy] != EL_SAND &&
1553 Feld[uxx][uyy] != EL_LANDMINE &&
1554 Feld[uxx][uyy] != EL_TRAP &&
1555 Feld[uxx][uyy] != EL_TRAP_ACTIVE) ||
1556 !IN_SCR_FIELD(xx, yy))
1559 if (i == 1 || i == 2)
1563 cx = (i == 1 ? TILEX - snip : 0);
1571 cy = (i==0 ? TILEY-snip : 0);
1574 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1575 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1577 MarkTileDirty(xx, yy);
1582 void DrawScreenElement(int x, int y, int element)
1584 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1585 DrawCrumbledSand(x, y);
1588 void DrawLevelElement(int x, int y, int element)
1590 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1591 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1594 void DrawScreenField(int x, int y)
1596 int ux = LEVELX(x), uy = LEVELY(y);
1597 int element, content;
1599 if (!IN_LEV_FIELD(ux, uy))
1601 if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
1604 element = BorderElement;
1606 DrawScreenElement(x, y, element);
1610 element = Feld[ux][uy];
1611 content = Store[ux][uy];
1613 if (IS_MOVING(ux, uy))
1615 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1616 boolean cut_mode = NO_CUTTING;
1618 if (element == EL_QUICKSAND_EMPTYING ||
1619 element == EL_MAGIC_WALL_EMPTYING ||
1620 element == EL_BD_MAGIC_WALL_EMPTYING ||
1621 element == EL_AMOEBA_DRIPPING)
1622 cut_mode = CUT_ABOVE;
1623 else if (element == EL_QUICKSAND_FILLING ||
1624 element == EL_MAGIC_WALL_FILLING ||
1625 element == EL_BD_MAGIC_WALL_FILLING)
1626 cut_mode = CUT_BELOW;
1628 if (cut_mode == CUT_ABOVE)
1629 DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1631 DrawScreenElement(x, y, EL_EMPTY);
1634 DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1635 else if (cut_mode == NO_CUTTING)
1636 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1638 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], content, cut_mode);
1640 if (content == EL_ACID)
1641 DrawLevelElementThruMask(ux, uy + 1, EL_ACID);
1643 else if (IS_BLOCKED(ux, uy))
1648 boolean cut_mode = NO_CUTTING;
1649 int element_old, content_old;
1651 Blocked2Moving(ux, uy, &oldx, &oldy);
1654 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1655 MovDir[oldx][oldy] == MV_RIGHT);
1657 element_old = Feld[oldx][oldy];
1658 content_old = Store[oldx][oldy];
1660 if (element_old == EL_QUICKSAND_EMPTYING ||
1661 element_old == EL_MAGIC_WALL_EMPTYING ||
1662 element_old == EL_BD_MAGIC_WALL_EMPTYING ||
1663 element_old == EL_AMOEBA_DRIPPING)
1664 cut_mode = CUT_ABOVE;
1666 DrawScreenElement(x, y, EL_EMPTY);
1669 DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
1671 else if (cut_mode == NO_CUTTING)
1672 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
1675 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
1678 else if (IS_DRAWABLE(element))
1679 DrawScreenElement(x, y, element);
1681 DrawScreenElement(x, y, EL_EMPTY);
1684 void DrawLevelField(int x, int y)
1686 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1687 DrawScreenField(SCREENX(x), SCREENY(y));
1688 else if (IS_MOVING(x, y))
1692 Moving2Blocked(x, y, &newx, &newy);
1693 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1694 DrawScreenField(SCREENX(newx), SCREENY(newy));
1696 else if (IS_BLOCKED(x, y))
1700 Blocked2Moving(x, y, &oldx, &oldy);
1701 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1702 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1706 void DrawMiniElement(int x, int y, int element)
1710 graphic = el2img(element);
1711 DrawMiniGraphic(x, y, graphic);
1714 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1716 int x = sx + scroll_x, y = sy + scroll_y;
1718 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1719 DrawMiniElement(sx, sy, EL_EMPTY);
1720 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1721 DrawMiniElement(sx, sy, Feld[x][y]);
1724 int steel_type, steel_position;
1727 { IMG_STEELWALL_TOPLEFT, IMG_INVISIBLE_STEELWALL_TOPLEFT },
1728 { IMG_STEELWALL_TOPRIGHT, IMG_INVISIBLE_STEELWALL_TOPRIGHT },
1729 { IMG_STEELWALL_BOTTOMLEFT, IMG_INVISIBLE_STEELWALL_BOTTOMLEFT },
1730 { IMG_STEELWALL_BOTTOMRIGHT, IMG_INVISIBLE_STEELWALL_BOTTOMRIGHT },
1731 { IMG_STEELWALL_VERTICAL, IMG_INVISIBLE_STEELWALL_VERTICAL },
1732 { IMG_STEELWALL_HORIZONTAL, IMG_INVISIBLE_STEELWALL_HORIZONTAL }
1735 steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
1736 steel_position = (x == -1 && y == -1 ? 0 :
1737 x == lev_fieldx && y == -1 ? 1 :
1738 x == -1 && y == lev_fieldy ? 2 :
1739 x == lev_fieldx && y == lev_fieldy ? 3 :
1740 x == -1 || x == lev_fieldx ? 4 :
1741 y == -1 || y == lev_fieldy ? 5 : -1);
1743 if (steel_position != -1)
1744 DrawMiniGraphic(sx, sy, border[steel_position][steel_type]);
1748 void getMicroGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1750 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
1751 int mini_startx = src_bitmap->width * 3 / 4;
1752 int mini_starty = src_bitmap->height * 2 / 3;
1753 int src_x = mini_startx + new_graphic_info[graphic].src_x / 8;
1754 int src_y = mini_starty + new_graphic_info[graphic].src_y / 8;
1756 if (src_x + MICRO_TILEX > src_bitmap->width ||
1757 src_y + MICRO_TILEY > src_bitmap->height)
1759 /* graphic of desired size seems not to be contained in this image;
1760 dirty workaround: get it from the middle of the normal sized image */
1762 getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
1763 src_x += (TILEX / 2 - MICRO_TILEX / 2);
1764 src_y += (TILEY / 2 - MICRO_TILEY / 2);
1767 *bitmap = src_bitmap;
1772 void DrawMicroElement(int xpos, int ypos, int element)
1776 int graphic = el2img(element);
1778 getMicroGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1779 BlitBitmap(src_bitmap, drawto, src_x, src_y, MICRO_TILEX, MICRO_TILEY,
1787 SetDrawBackgroundMask(REDRAW_NONE);
1790 for(x=BX1; x<=BX2; x++)
1791 for(y=BY1; y<=BY2; y++)
1792 DrawScreenField(x, y);
1794 redraw_mask |= REDRAW_FIELD;
1797 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1801 for(x=0; x<size_x; x++)
1802 for(y=0; y<size_y; y++)
1803 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1805 redraw_mask |= REDRAW_FIELD;
1808 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1812 DrawBackground(xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
1814 if (lev_fieldx < STD_LEV_FIELDX)
1815 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1816 if (lev_fieldy < STD_LEV_FIELDY)
1817 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1819 xpos += MICRO_TILEX;
1820 ypos += MICRO_TILEY;
1822 for(x=-1; x<=STD_LEV_FIELDX; x++)
1824 for(y=-1; y<=STD_LEV_FIELDY; y++)
1826 int lx = from_x + x, ly = from_y + y;
1828 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1829 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1831 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1
1832 && BorderElement != EL_EMPTY)
1833 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1838 redraw_mask |= REDRAW_MICROLEVEL;
1841 #define MICROLABEL_EMPTY 0
1842 #define MICROLABEL_LEVEL_NAME 1
1843 #define MICROLABEL_CREATED_BY 2
1844 #define MICROLABEL_LEVEL_AUTHOR 3
1845 #define MICROLABEL_IMPORTED_FROM 4
1846 #define MICROLABEL_LEVEL_IMPORT_INFO 5
1848 #define MAX_MICROLABEL_SIZE (SXSIZE / FONT4_XSIZE)
1850 static void DrawMicroLevelLabelExt(int mode)
1852 char label_text[MAX_MICROLABEL_SIZE + 1];
1854 DrawBackground(SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
1856 strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
1857 mode == MICROLABEL_CREATED_BY ? "created by" :
1858 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
1859 mode == MICROLABEL_IMPORTED_FROM ? "imported from" :
1860 mode == MICROLABEL_LEVEL_IMPORT_INFO ?
1861 leveldir_current->imported_from : ""),
1862 MAX_MICROLABEL_SIZE);
1863 label_text[MAX_MICROLABEL_SIZE] = '\0';
1865 if (strlen(label_text) > 0)
1867 int lxpos = SX + (SXSIZE - strlen(label_text) * FONT4_XSIZE) / 2;
1868 int lypos = MICROLABEL_YPOS;
1870 DrawText(lxpos, lypos, label_text, FS_SMALL, FC_SPECIAL2);
1873 redraw_mask |= REDRAW_MICROLEVEL;
1876 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1878 static unsigned long scroll_delay = 0;
1879 static unsigned long label_delay = 0;
1880 static int from_x, from_y, scroll_direction;
1881 static int label_state, label_counter;
1885 from_x = from_y = 0;
1886 scroll_direction = MV_RIGHT;
1890 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1891 DrawMicroLevelLabelExt(label_state);
1893 /* initialize delay counters */
1894 DelayReached(&scroll_delay, 0);
1895 DelayReached(&label_delay, 0);
1900 /* scroll micro level, if needed */
1901 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1902 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1904 switch (scroll_direction)
1910 scroll_direction = MV_UP;
1914 if (from_x < lev_fieldx - STD_LEV_FIELDX)
1917 scroll_direction = MV_DOWN;
1924 scroll_direction = MV_RIGHT;
1928 if (from_y < lev_fieldy - STD_LEV_FIELDY)
1931 scroll_direction = MV_LEFT;
1938 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1941 /* redraw micro level label, if needed */
1942 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1943 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1944 strcmp(level.author, leveldir_current->name) != 0 &&
1945 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1947 int max_label_counter = 23;
1949 if (leveldir_current->imported_from != NULL)
1950 max_label_counter += 14;
1952 label_counter = (label_counter + 1) % max_label_counter;
1953 label_state = (label_counter >= 0 && label_counter <= 7 ?
1954 MICROLABEL_LEVEL_NAME :
1955 label_counter >= 9 && label_counter <= 12 ?
1956 MICROLABEL_CREATED_BY :
1957 label_counter >= 14 && label_counter <= 21 ?
1958 MICROLABEL_LEVEL_AUTHOR :
1959 label_counter >= 23 && label_counter <= 26 ?
1960 MICROLABEL_IMPORTED_FROM :
1961 label_counter >= 28 && label_counter <= 35 ?
1962 MICROLABEL_LEVEL_IMPORT_INFO : MICROLABEL_EMPTY);
1963 DrawMicroLevelLabelExt(label_state);
1967 int REQ_in_range(int x, int y)
1969 if (y > DY+249 && y < DY+278)
1971 if (x > DX+1 && x < DX+48)
1973 else if (x > DX+51 && x < DX+98)
1979 #define MAX_REQUEST_LINES 13
1980 #define MAX_REQUEST_LINE_LEN 7
1982 boolean Request(char *text, unsigned int req_state)
1984 int mx, my, ty, result = -1;
1985 unsigned int old_door_state;
1987 #if defined(PLATFORM_UNIX)
1988 /* pause network game while waiting for request to answer */
1989 if (options.network &&
1990 game_status == PLAYING &&
1991 req_state & REQUEST_WAIT_FOR)
1992 SendToServer_PausePlaying();
1995 old_door_state = GetDoorState();
1999 CloseDoor(DOOR_CLOSE_1);
2001 /* save old door content */
2002 BlitBitmap(bitmap_db_door, bitmap_db_door,
2003 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
2004 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
2006 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
2008 /* clear door drawing field */
2009 DrawBackground(DX, DY, DXSIZE, DYSIZE);
2011 /* write text for request */
2012 for(ty=0; ty < MAX_REQUEST_LINES; ty++)
2014 char text_line[MAX_REQUEST_LINE_LEN + 1];
2020 for(tl=0,tx=0; tx < MAX_REQUEST_LINE_LEN; tl++,tx++)
2023 if (!tc || tc == ' ')
2034 strncpy(text_line, text, tl);
2037 DrawText(DX + 50 - (tl * 14)/2, DY + 8 + ty * 16,
2038 text_line, FS_SMALL, FC_YELLOW);
2040 text += tl + (tc == ' ' ? 1 : 0);
2043 if (req_state & REQ_ASK)
2045 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
2046 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
2048 else if (req_state & REQ_CONFIRM)
2050 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
2052 else if (req_state & REQ_PLAYER)
2054 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
2055 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
2056 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
2057 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
2060 /* copy request gadgets to door backbuffer */
2061 BlitBitmap(drawto, bitmap_db_door,
2062 DX, DY, DXSIZE, DYSIZE,
2063 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2065 OpenDoor(DOOR_OPEN_1);
2071 if (!(req_state & REQUEST_WAIT_FOR))
2073 SetDrawBackgroundMask(REDRAW_FIELD);
2078 if (game_status != MAINMENU)
2081 button_status = MB_RELEASED;
2083 request_gadget_id = -1;
2085 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
2097 case EVENT_BUTTONPRESS:
2098 case EVENT_BUTTONRELEASE:
2099 case EVENT_MOTIONNOTIFY:
2101 if (event.type == EVENT_MOTIONNOTIFY)
2103 if (!PointerInWindow(window))
2104 continue; /* window and pointer are on different screens */
2109 motion_status = TRUE;
2110 mx = ((MotionEvent *) &event)->x;
2111 my = ((MotionEvent *) &event)->y;
2115 motion_status = FALSE;
2116 mx = ((ButtonEvent *) &event)->x;
2117 my = ((ButtonEvent *) &event)->y;
2118 if (event.type == EVENT_BUTTONPRESS)
2119 button_status = ((ButtonEvent *) &event)->button;
2121 button_status = MB_RELEASED;
2124 /* this sets 'request_gadget_id' */
2125 HandleGadgets(mx, my, button_status);
2127 switch(request_gadget_id)
2129 case TOOL_CTRL_ID_YES:
2132 case TOOL_CTRL_ID_NO:
2135 case TOOL_CTRL_ID_CONFIRM:
2136 result = TRUE | FALSE;
2139 case TOOL_CTRL_ID_PLAYER_1:
2142 case TOOL_CTRL_ID_PLAYER_2:
2145 case TOOL_CTRL_ID_PLAYER_3:
2148 case TOOL_CTRL_ID_PLAYER_4:
2159 case EVENT_KEYPRESS:
2160 switch(GetEventKey((KeyEvent *)&event, TRUE))
2173 if (req_state & REQ_PLAYER)
2177 case EVENT_KEYRELEASE:
2178 ClearPlayerAction();
2182 HandleOtherEvents(&event);
2186 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2188 int joy = AnyJoystick();
2190 if (joy & JOY_BUTTON_1)
2192 else if (joy & JOY_BUTTON_2)
2198 /* don't eat all CPU time */
2202 if (game_status != MAINMENU)
2207 if (!(req_state & REQ_STAY_OPEN))
2209 CloseDoor(DOOR_CLOSE_1);
2211 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
2213 BlitBitmap(bitmap_db_door, bitmap_db_door,
2214 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
2215 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
2216 OpenDoor(DOOR_OPEN_1);
2222 SetDrawBackgroundMask(REDRAW_FIELD);
2224 #if defined(PLATFORM_UNIX)
2225 /* continue network game after request */
2226 if (options.network &&
2227 game_status == PLAYING &&
2228 req_state & REQUEST_WAIT_FOR)
2229 SendToServer_ContinuePlaying();
2235 unsigned int OpenDoor(unsigned int door_state)
2237 unsigned int new_door_state;
2239 if (door_state & DOOR_COPY_BACK)
2241 BlitBitmap(bitmap_db_door, bitmap_db_door,
2242 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
2243 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2244 door_state &= ~DOOR_COPY_BACK;
2247 new_door_state = MoveDoor(door_state);
2249 return(new_door_state);
2252 unsigned int CloseDoor(unsigned int door_state)
2254 unsigned int new_door_state;
2256 BlitBitmap(backbuffer, bitmap_db_door,
2257 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2258 BlitBitmap(backbuffer, bitmap_db_door,
2259 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2261 new_door_state = MoveDoor(door_state);
2263 return(new_door_state);
2266 unsigned int GetDoorState()
2268 return MoveDoor(DOOR_GET_STATE);
2271 unsigned int SetDoorState(unsigned int door_state)
2273 return MoveDoor(door_state | DOOR_SET_STATE);
2276 unsigned int MoveDoor(unsigned int door_state)
2278 static int door1 = DOOR_OPEN_1;
2279 static int door2 = DOOR_CLOSE_2;
2280 static unsigned long door_delay = 0;
2281 int x, start, stepsize = 2;
2282 unsigned long door_delay_value = stepsize * 5;
2284 if (door_state == DOOR_GET_STATE)
2285 return(door1 | door2);
2287 if (door_state & DOOR_SET_STATE)
2289 if (door_state & DOOR_ACTION_1)
2290 door1 = door_state & DOOR_ACTION_1;
2291 if (door_state & DOOR_ACTION_2)
2292 door2 = door_state & DOOR_ACTION_2;
2294 return(door1 | door2);
2297 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2298 door_state &= ~DOOR_OPEN_1;
2299 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2300 door_state &= ~DOOR_CLOSE_1;
2301 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2302 door_state &= ~DOOR_OPEN_2;
2303 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2304 door_state &= ~DOOR_CLOSE_2;
2306 if (setup.quick_doors)
2309 door_delay_value = 0;
2311 StopSound(SND_MENU_DOOR_OPENING);
2312 StopSound(SND_MENU_DOOR_CLOSING);
2315 if (global.autoplay_leveldir)
2317 door_state |= DOOR_NO_DELAY;
2318 door_state &= ~DOOR_CLOSE_ALL;
2321 if (door_state & DOOR_ACTION)
2323 if (!(door_state & DOOR_NO_DELAY))
2325 /* opening door sound has priority over simultaneously closing door */
2326 if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
2327 PlaySoundStereo(SND_MENU_DOOR_OPENING, SOUND_MAX_RIGHT);
2328 else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
2329 PlaySoundStereo(SND_MENU_DOOR_CLOSING, SOUND_MAX_RIGHT);
2332 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2334 for(x=start; x<=DXSIZE; x+=stepsize)
2336 Bitmap *bitmap = new_graphic_info[IMG_GLOBAL_DOOR].bitmap;
2337 GC gc = bitmap->stored_clip_gc;
2339 if (!(door_state & DOOR_NO_DELAY))
2340 WaitUntilDelayReached(&door_delay, door_delay_value);
2342 if (door_state & DOOR_ACTION_1)
2344 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
2345 int j = (DXSIZE - i) / 3;
2347 BlitBitmap(bitmap_db_door, drawto,
2348 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
2349 DXSIZE,DYSIZE - i/2, DX, DY);
2351 ClearRectangle(drawto, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
2353 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2354 BlitBitmapMasked(bitmap, drawto,
2355 DXSIZE, DOOR_GFX_PAGEY1, i, 77,
2356 DX + DXSIZE - i, DY + j);
2357 BlitBitmapMasked(bitmap, drawto,
2358 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
2359 DX + DXSIZE - i, DY + 140 + j);
2360 SetClipOrigin(bitmap, gc, DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
2361 BlitBitmapMasked(bitmap, drawto,
2362 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
2364 BlitBitmapMasked(bitmap, drawto,
2365 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
2368 BlitBitmapMasked(bitmap, drawto,
2369 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2371 BlitBitmapMasked(bitmap, drawto,
2372 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2374 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2375 BlitBitmapMasked(bitmap, drawto,
2376 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2377 DX + DXSIZE - i, DY + 77 + j);
2378 BlitBitmapMasked(bitmap, drawto,
2379 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2380 DX + DXSIZE - i, DY + 203 + j);
2382 redraw_mask |= REDRAW_DOOR_1;
2385 if (door_state & DOOR_ACTION_2)
2387 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
2388 int j = (VXSIZE - i) / 3;
2390 BlitBitmap(bitmap_db_door, drawto,
2391 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
2392 VXSIZE, VYSIZE - i/2, VX, VY);
2394 ClearRectangle(drawto, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
2396 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2397 BlitBitmapMasked(bitmap, drawto,
2398 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
2399 VX + VXSIZE-i, VY+j);
2400 SetClipOrigin(bitmap, gc,
2401 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2402 BlitBitmapMasked(bitmap, drawto,
2403 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
2406 BlitBitmapMasked(bitmap, drawto,
2407 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2408 i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
2409 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2410 BlitBitmapMasked(bitmap, drawto,
2411 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2413 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2415 redraw_mask |= REDRAW_DOOR_2;
2420 if (game_status == MAINMENU)
2425 if (setup.quick_doors)
2427 StopSound(SND_MENU_DOOR_OPENING);
2428 StopSound(SND_MENU_DOOR_CLOSING);
2431 if (door_state & DOOR_ACTION_1)
2432 door1 = door_state & DOOR_ACTION_1;
2433 if (door_state & DOOR_ACTION_2)
2434 door2 = door_state & DOOR_ACTION_2;
2436 return (door1 | door2);
2439 void DrawSpecialEditorDoor()
2441 /* draw bigger toolbox window */
2442 BlitBitmap(new_graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
2443 DOOR_GFX_PAGEX7, 0, EXSIZE + 8, 8,
2445 BlitBitmap(new_graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2446 EX - 4, VY - 4, EXSIZE + 8, EYSIZE - VYSIZE + 4,
2449 redraw_mask |= REDRAW_ALL;
2452 void UndrawSpecialEditorDoor()
2454 /* draw normal tape recorder window */
2455 BlitBitmap(new_graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2456 EX - 4, EY - 12, EXSIZE + 8, EYSIZE - VYSIZE + 12,
2459 redraw_mask |= REDRAW_ALL;
2463 int ReadPixel(DrawBuffer *bitmap, int x, int y)
2465 XImage *pixel_image;
2466 unsigned long pixel_value;
2468 pixel_image = XGetImage(display, bitmap->drawable,
2469 x, y, 1, 1, AllPlanes, ZPixmap);
2470 pixel_value = XGetPixel(pixel_image, 0, 0);
2472 XDestroyImage(pixel_image);
2478 /* ---------- new tool button stuff ---------------------------------------- */
2480 /* graphic position values for tool buttons */
2481 #define TOOL_BUTTON_YES_XPOS 2
2482 #define TOOL_BUTTON_YES_YPOS 250
2483 #define TOOL_BUTTON_YES_GFX_YPOS 0
2484 #define TOOL_BUTTON_YES_XSIZE 46
2485 #define TOOL_BUTTON_YES_YSIZE 28
2486 #define TOOL_BUTTON_NO_XPOS 52
2487 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2488 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2489 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2490 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2491 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2492 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2493 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2494 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2495 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2496 #define TOOL_BUTTON_PLAYER_XSIZE 30
2497 #define TOOL_BUTTON_PLAYER_YSIZE 30
2498 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2499 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2500 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2501 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2502 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2503 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2504 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2505 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2506 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2507 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2508 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2509 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2510 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2511 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2512 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2513 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2514 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2515 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2516 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2517 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2526 } toolbutton_info[NUM_TOOL_BUTTONS] =
2529 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2530 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2531 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2536 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2537 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2538 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2543 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2544 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2545 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2546 TOOL_CTRL_ID_CONFIRM,
2550 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2551 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2552 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2553 TOOL_CTRL_ID_PLAYER_1,
2557 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2558 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2559 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2560 TOOL_CTRL_ID_PLAYER_2,
2564 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2565 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2566 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2567 TOOL_CTRL_ID_PLAYER_3,
2571 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2572 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2573 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2574 TOOL_CTRL_ID_PLAYER_4,
2579 void CreateToolButtons()
2583 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2585 Bitmap *gd_bitmap = new_graphic_info[IMG_GLOBAL_DOOR].bitmap;
2586 Bitmap *deco_bitmap = None;
2587 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2588 struct GadgetInfo *gi;
2589 unsigned long event_mask;
2590 int gd_xoffset, gd_yoffset;
2591 int gd_x1, gd_x2, gd_y;
2594 event_mask = GD_EVENT_RELEASED;
2596 gd_xoffset = toolbutton_info[i].xpos;
2597 gd_yoffset = toolbutton_info[i].ypos;
2598 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2599 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2600 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2602 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2604 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
2606 getMiniGraphicSource(PLAYER_NR_GFX(IMG_PLAYER1, player_nr),
2607 &deco_bitmap, &deco_x, &deco_y);
2608 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2609 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2612 gi = CreateGadget(GDI_CUSTOM_ID, id,
2613 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2614 GDI_X, DX + toolbutton_info[i].x,
2615 GDI_Y, DY + toolbutton_info[i].y,
2616 GDI_WIDTH, toolbutton_info[i].width,
2617 GDI_HEIGHT, toolbutton_info[i].height,
2618 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2619 GDI_STATE, GD_BUTTON_UNPRESSED,
2620 GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
2621 GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
2622 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
2623 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2624 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2625 GDI_DECORATION_SHIFTING, 1, 1,
2626 GDI_EVENT_MASK, event_mask,
2627 GDI_CALLBACK_ACTION, HandleToolButtons,
2631 Error(ERR_EXIT, "cannot create gadget");
2633 tool_gadget[id] = gi;
2637 void FreeToolButtons()
2641 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2642 FreeGadget(tool_gadget[i]);
2645 static void UnmapToolButtons()
2649 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2650 UnmapGadget(tool_gadget[i]);
2653 static void HandleToolButtons(struct GadgetInfo *gi)
2655 request_gadget_id = gi->custom_id;
2658 int get_next_element(int element)
2662 case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL;
2663 case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY;
2664 case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL;
2665 case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_ACTIVE;
2666 case EL_BD_MAGIC_WALL_FILLING: return EL_BD_MAGIC_WALL_FULL;
2667 case EL_BD_MAGIC_WALL_EMPTYING: return EL_BD_MAGIC_WALL_ACTIVE;
2668 case EL_AMOEBA_DRIPPING: return EL_AMOEBA_WET;
2670 default: return element;
2674 int el2gfx_OLD(int element)
2678 case EL_EMPTY: return -1;
2679 case EL_SAND: return GFX_ERDREICH;
2680 case EL_WALL: return GFX_MAUERWERK;
2681 case EL_WALL_CRUMBLED: return GFX_FELSBODEN;
2682 case EL_ROCK: return GFX_FELSBROCKEN;
2683 case EL_EMERALD: return GFX_EDELSTEIN;
2684 case EL_EXIT_CLOSED: return GFX_AUSGANG_ZU;
2685 case EL_EXIT_OPENING: return GFX_AUSGANG_ACT;
2686 case EL_EXIT_OPEN: return GFX_AUSGANG_AUF;
2687 case EL_SP_EXIT_OPEN: return GFX_SP_EXIT;
2688 case EL_PLAYER1: return GFX_SPIELER1;
2689 case EL_PLAYER2: return GFX_SPIELER2;
2690 case EL_PLAYER3: return GFX_SPIELER3;
2691 case EL_PLAYER4: return GFX_SPIELER4;
2692 case EL_BUG: return GFX_KAEFER;
2693 case EL_BUG_RIGHT: return GFX_KAEFER_RIGHT;
2694 case EL_BUG_UP: return GFX_KAEFER_UP;
2695 case EL_BUG_LEFT: return GFX_KAEFER_LEFT;
2696 case EL_BUG_DOWN: return GFX_KAEFER_DOWN;
2697 case EL_SPACESHIP: return GFX_FLIEGER;
2698 case EL_SPACESHIP_RIGHT: return GFX_FLIEGER_RIGHT;
2699 case EL_SPACESHIP_UP: return GFX_FLIEGER_UP;
2700 case EL_SPACESHIP_LEFT: return GFX_FLIEGER_LEFT;
2701 case EL_SPACESHIP_DOWN: return GFX_FLIEGER_DOWN;
2702 case EL_BD_BUTTERFLY: return GFX_BUTTERFLY;
2703 case EL_BD_BUTTERFLY_RIGHT: return GFX_BUTTERFLY_RIGHT;
2704 case EL_BD_BUTTERFLY_UP: return GFX_BUTTERFLY_UP;
2705 case EL_BD_BUTTERFLY_LEFT: return GFX_BUTTERFLY_LEFT;
2706 case EL_BD_BUTTERFLY_DOWN: return GFX_BUTTERFLY_DOWN;
2707 case EL_BD_FIREFLY: return GFX_FIREFLY;
2708 case EL_BD_FIREFLY_RIGHT: return GFX_FIREFLY_RIGHT;
2709 case EL_BD_FIREFLY_UP: return GFX_FIREFLY_UP;
2710 case EL_BD_FIREFLY_LEFT: return GFX_FIREFLY_LEFT;
2711 case EL_BD_FIREFLY_DOWN: return GFX_FIREFLY_DOWN;
2712 case EL_YAMYAM: return GFX_MAMPFER;
2713 case EL_ROBOT: return GFX_ROBOT;
2714 case EL_STEELWALL: return GFX_BETON;
2715 case EL_DIAMOND: return GFX_DIAMANT;
2716 case EL_QUICKSAND_EMPTY: return GFX_MORAST_LEER;
2717 case EL_QUICKSAND_FULL: return GFX_MORAST_VOLL;
2718 case EL_QUICKSAND_EMPTYING: return GFX_MORAST_LEER;
2719 case EL_AMOEBA_DROP: return GFX_TROPFEN;
2720 case EL_BOMB: return GFX_BOMBE;
2721 case EL_MAGIC_WALL: return GFX_MAGIC_WALL_OFF;
2722 case EL_MAGIC_WALL_ACTIVE: return GFX_MAGIC_WALL_EMPTY;
2723 case EL_MAGIC_WALL_EMPTYING: return GFX_MAGIC_WALL_EMPTY;
2724 case EL_MAGIC_WALL_FULL: return GFX_MAGIC_WALL_FULL;
2725 case EL_MAGIC_WALL_DEAD: return GFX_MAGIC_WALL_DEAD;
2726 case EL_ACID: return GFX_SALZSAEURE;
2727 case EL_AMOEBA_DEAD: return GFX_AMOEBE_TOT;
2728 case EL_AMOEBA_WET: return GFX_AMOEBE_NASS;
2729 case EL_AMOEBA_DRY: return GFX_AMOEBE_NORM;
2730 case EL_AMOEBA_FULL: return GFX_AMOEBE_VOLL;
2731 case EL_BD_AMOEBA: return GFX_AMOEBE_BD;
2732 case EL_AMOEBA_TO_DIAMOND: return GFX_AMOEBA2DIAM;
2733 case EL_AMOEBA_DRIPPING: return GFX_AMOEBE_NASS;
2734 case EL_NUT: return GFX_KOKOSNUSS;
2735 case EL_GAMEOFLIFE: return GFX_LIFE;
2736 case EL_BIOMAZE: return GFX_LIFE_ASYNC;
2737 case EL_DYNAMITE_ACTIVE: return GFX_DYNAMIT;
2738 case EL_STONEBLOCK: return GFX_BADEWANNE;
2739 case EL_ACIDPOOL_TOPLEFT: return GFX_BADEWANNE1;
2740 case EL_ACIDPOOL_TOPRIGHT: return GFX_BADEWANNE2;
2741 case EL_ACIDPOOL_BOTTOMLEFT: return GFX_BADEWANNE3;
2742 case EL_ACIDPOOL_BOTTOM: return GFX_BADEWANNE4;
2743 case EL_ACIDPOOL_BOTTOMRIGHT: return GFX_BADEWANNE5;
2744 case EL_ROBOT_WHEEL: return GFX_ABLENK_AUS;
2745 case EL_ROBOT_WHEEL_ACTIVE: return GFX_ABLENK_EIN;
2746 case EL_KEY1: return GFX_SCHLUESSEL1;
2747 case EL_KEY2: return GFX_SCHLUESSEL2;
2748 case EL_KEY3: return GFX_SCHLUESSEL3;
2749 case EL_KEY4: return GFX_SCHLUESSEL4;
2750 case EL_GATE1: return GFX_PFORTE1;
2751 case EL_GATE2: return GFX_PFORTE2;
2752 case EL_GATE3: return GFX_PFORTE3;
2753 case EL_GATE4: return GFX_PFORTE4;
2754 case EL_GATE1_GRAY: return GFX_PFORTE1X;
2755 case EL_GATE2_GRAY: return GFX_PFORTE2X;
2756 case EL_GATE3_GRAY: return GFX_PFORTE3X;
2757 case EL_GATE4_GRAY: return GFX_PFORTE4X;
2758 case EL_DYNAMITE: return GFX_DYNAMIT_AUS;
2759 case EL_PACMAN: return GFX_PACMAN;
2760 case EL_PACMAN_RIGHT: return GFX_PACMAN_RIGHT;
2761 case EL_PACMAN_UP: return GFX_PACMAN_UP;
2762 case EL_PACMAN_LEFT: return GFX_PACMAN_LEFT;
2763 case EL_PACMAN_DOWN: return GFX_PACMAN_DOWN;
2764 case EL_INVISIBLE_WALL: return GFX_UNSICHTBAR;
2765 case EL_INVISIBLE_WALL_ACTIVE: return GFX_UNSICHTBAR_ON;
2766 case EL_WALL_EMERALD: return GFX_ERZ_EDEL;
2767 case EL_WALL_DIAMOND: return GFX_ERZ_DIAM;
2768 case EL_LAMP: return GFX_BIRNE_AUS;
2769 case EL_LAMP_ACTIVE: return GFX_BIRNE_EIN;
2770 case EL_TIME_ORB_FULL: return GFX_ZEIT_VOLL;
2771 case EL_TIME_ORB_EMPTY: return GFX_ZEIT_LEER;
2772 case EL_WALL_GROWING: return GFX_MAUER_LEBT;
2773 case EL_WALL_GROWING_X: return GFX_MAUER_X;
2774 case EL_WALL_GROWING_Y: return GFX_MAUER_Y;
2775 case EL_WALL_GROWING_XY: return GFX_MAUER_XY;
2776 case EL_BD_DIAMOND: return GFX_EDELSTEIN_BD;
2777 case EL_EMERALD_YELLOW: return GFX_EDELSTEIN_GELB;
2778 case EL_EMERALD_RED: return GFX_EDELSTEIN_ROT;
2779 case EL_EMERALD_PURPLE: return GFX_EDELSTEIN_LILA;
2780 case EL_WALL_BD_DIAMOND: return GFX_ERZ_EDEL_BD;
2781 case EL_WALL_EMERALD_YELLOW: return GFX_ERZ_EDEL_GELB;
2782 case EL_WALL_EMERALD_RED: return GFX_ERZ_EDEL_ROT;
2783 case EL_WALL_EMERALD_PURPLE: return GFX_ERZ_EDEL_LILA;
2784 case EL_DARK_YAMYAM: return GFX_MAMPFER2;
2785 case EL_BD_MAGIC_WALL: return GFX_MAGIC_WALL_BD_OFF;
2786 case EL_BD_MAGIC_WALL_ACTIVE: return GFX_MAGIC_WALL_BD_EMPTY;
2787 case EL_BD_MAGIC_WALL_EMPTYING: return GFX_MAGIC_WALL_BD_EMPTY;
2788 case EL_BD_MAGIC_WALL_FULL: return GFX_MAGIC_WALL_BD_FULL;
2789 case EL_BD_MAGIC_WALL_DEAD: return GFX_MAGIC_WALL_BD_DEAD;
2790 case EL_DYNABOMB_PLAYER1_ACTIVE: return GFX_DYNABOMB;
2791 case EL_DYNABOMB_PLAYER2_ACTIVE: return GFX_DYNABOMB;
2792 case EL_DYNABOMB_PLAYER3_ACTIVE: return GFX_DYNABOMB;
2793 case EL_DYNABOMB_PLAYER4_ACTIVE: return GFX_DYNABOMB;
2794 case EL_DYNABOMB_NR: return GFX_DYNABOMB_NR;
2795 case EL_DYNABOMB_SZ: return GFX_DYNABOMB_SZ;
2796 case EL_DYNABOMB_XL: return GFX_DYNABOMB_XL;
2797 case EL_SOKOBAN_OBJECT: return GFX_SOKOBAN_OBJEKT;
2798 case EL_SOKOBAN_FIELD_EMPTY: return GFX_SOKOBAN_FELD_LEER;
2799 case EL_SOKOBAN_FIELD_FULL: return GFX_SOKOBAN_FELD_VOLL;
2800 case EL_MOLE: return GFX_MOLE;
2801 case EL_PENGUIN: return GFX_PINGUIN;
2802 case EL_PIG: return GFX_SCHWEIN;
2803 case EL_DRAGON: return GFX_DRACHE;
2804 case EL_SATELLITE: return GFX_SONDE;
2805 case EL_ARROW_BLUE_LEFT: return GFX_PFEIL_LEFT;
2806 case EL_ARROW_BLUE_RIGHT: return GFX_PFEIL_RIGHT;
2807 case EL_ARROW_BLUE_UP: return GFX_PFEIL_UP;
2808 case EL_ARROW_BLUE_DOWN: return GFX_PFEIL_DOWN;
2809 case EL_SPEED_PILL: return GFX_SPEED_PILL;
2810 case EL_SP_TERMINAL_ACTIVE: return GFX_SP_TERMINAL;
2811 case EL_SP_BUGGY_BASE_ACTIVE: return GFX_SP_BUG_ACTIVE;
2812 case EL_SP_ZONK: return GFX_SP_ZONK;
2813 /* ^^^^^^^^^^ non-standard position in supaplex graphic set! */
2814 case EL_INVISIBLE_STEELWALL: return GFX_INVISIBLE_STEEL;
2815 case EL_INVISIBLE_STEELWALL_ACTIVE: return GFX_INVISIBLE_STEEL_ON;
2816 case EL_BLACK_ORB: return GFX_BLACK_ORB;
2817 case EL_EM_GATE1: return GFX_EM_GATE_1;
2818 case EL_EM_GATE2: return GFX_EM_GATE_2;
2819 case EL_EM_GATE3: return GFX_EM_GATE_3;
2820 case EL_EM_GATE4: return GFX_EM_GATE_4;
2821 case EL_EM_GATE1_GRAY: return GFX_EM_GATE_1X;
2822 case EL_EM_GATE2_GRAY: return GFX_EM_GATE_2X;
2823 case EL_EM_GATE3_GRAY: return GFX_EM_GATE_3X;
2824 case EL_EM_GATE4_GRAY: return GFX_EM_GATE_4X;
2825 case EL_EM_KEY1_FILE: return GFX_EM_KEY_1;
2826 case EL_EM_KEY2_FILE: return GFX_EM_KEY_2;
2827 case EL_EM_KEY3_FILE: return GFX_EM_KEY_3;
2828 case EL_EM_KEY4_FILE: return GFX_EM_KEY_4;
2829 case EL_EM_KEY1: return GFX_EM_KEY_1;
2830 case EL_EM_KEY2: return GFX_EM_KEY_2;
2831 case EL_EM_KEY3: return GFX_EM_KEY_3;
2832 case EL_EM_KEY4: return GFX_EM_KEY_4;
2833 case EL_PEARL: return GFX_PEARL;
2834 case EL_CRYSTAL: return GFX_CRYSTAL;
2835 case EL_WALL_PEARL: return GFX_WALL_PEARL;
2836 case EL_WALL_CRYSTAL: return GFX_WALL_CRYSTAL;
2837 case EL_DOOR_WHITE: return GFX_DOOR_WHITE;
2838 case EL_DOOR_WHITE_GRAY: return GFX_DOOR_WHITE_GRAY;
2839 case EL_KEY_WHITE: return GFX_KEY_WHITE;
2840 case EL_SHIELD_NORMAL: return GFX_SHIELD_PASSIVE;
2841 case EL_SHIELD_DEADLY: return GFX_SHIELD_ACTIVE;
2842 case EL_EXTRA_TIME: return GFX_EXTRA_TIME;
2843 case EL_SWITCHGATE_OPEN: return GFX_SWITCHGATE_OPEN;
2844 case EL_SWITCHGATE_CLOSED: return GFX_SWITCHGATE_CLOSED;
2845 case EL_SWITCHGATE_SWITCH_UP: return GFX_SWITCHGATE_SWITCH_1;
2846 case EL_SWITCHGATE_SWITCH_DOWN: return GFX_SWITCHGATE_SWITCH_2;
2847 case EL_CONVEYOR_BELT1_LEFT: return GFX_BELT1_LEFT;
2848 case EL_CONVEYOR_BELT1_MIDDLE: return GFX_BELT1_MIDDLE;
2849 case EL_CONVEYOR_BELT1_RIGHT: return GFX_BELT1_RIGHT;
2850 case EL_CONVEYOR_BELT1_LEFT_ACTIVE: return GFX_BELT1_LEFT;
2851 case EL_CONVEYOR_BELT1_MIDDLE_ACTIVE:return GFX_BELT1_MIDDLE;
2852 case EL_CONVEYOR_BELT1_RIGHT_ACTIVE:return GFX_BELT1_RIGHT;
2853 case EL_CONVEYOR_BELT1_SWITCH_LEFT: return GFX_BELT1_SWITCH_LEFT;
2854 case EL_CONVEYOR_BELT1_SWITCH_MIDDLE:return GFX_BELT1_SWITCH_MIDDLE;
2855 case EL_CONVEYOR_BELT1_SWITCH_RIGHT:return GFX_BELT1_SWITCH_RIGHT;
2856 case EL_CONVEYOR_BELT2_LEFT: return GFX_BELT2_LEFT;
2857 case EL_CONVEYOR_BELT2_MIDDLE: return GFX_BELT2_MIDDLE;
2858 case EL_CONVEYOR_BELT2_RIGHT: return GFX_BELT2_RIGHT;
2859 case EL_CONVEYOR_BELT2_LEFT_ACTIVE: return GFX_BELT2_LEFT;
2860 case EL_CONVEYOR_BELT2_MIDDLE_ACTIVE:return GFX_BELT2_MIDDLE;
2861 case EL_CONVEYOR_BELT2_RIGHT_ACTIVE:return GFX_BELT2_RIGHT;
2862 case EL_CONVEYOR_BELT2_SWITCH_LEFT: return GFX_BELT2_SWITCH_LEFT;
2863 case EL_CONVEYOR_BELT2_SWITCH_MIDDLE:return GFX_BELT2_SWITCH_MIDDLE;
2864 case EL_CONVEYOR_BELT2_SWITCH_RIGHT:return GFX_BELT2_SWITCH_RIGHT;
2865 case EL_CONVEYOR_BELT3_LEFT: return GFX_BELT3_LEFT;
2866 case EL_CONVEYOR_BELT3_MIDDLE: return GFX_BELT3_MIDDLE;
2867 case EL_CONVEYOR_BELT3_RIGHT: return GFX_BELT3_RIGHT;
2868 case EL_CONVEYOR_BELT3_LEFT_ACTIVE: return GFX_BELT3_LEFT;
2869 case EL_CONVEYOR_BELT3_MIDDLE_ACTIVE:return GFX_BELT3_MIDDLE;
2870 case EL_CONVEYOR_BELT3_RIGHT_ACTIVE:return GFX_BELT3_RIGHT;
2871 case EL_CONVEYOR_BELT3_SWITCH_LEFT: return GFX_BELT3_SWITCH_LEFT;
2872 case EL_CONVEYOR_BELT3_SWITCH_MIDDLE:return GFX_BELT3_SWITCH_MIDDLE;
2873 case EL_CONVEYOR_BELT3_SWITCH_RIGHT:return GFX_BELT3_SWITCH_RIGHT;
2874 case EL_CONVEYOR_BELT4_LEFT: return GFX_BELT4_LEFT;
2875 case EL_CONVEYOR_BELT4_MIDDLE: return GFX_BELT4_MIDDLE;
2876 case EL_CONVEYOR_BELT4_RIGHT: return GFX_BELT4_RIGHT;
2877 case EL_CONVEYOR_BELT4_LEFT_ACTIVE: return GFX_BELT4_LEFT;
2878 case EL_CONVEYOR_BELT4_MIDDLE_ACTIVE:return GFX_BELT4_MIDDLE;
2879 case EL_CONVEYOR_BELT4_RIGHT_ACTIVE:return GFX_BELT4_RIGHT;
2880 case EL_CONVEYOR_BELT4_SWITCH_LEFT: return GFX_BELT4_SWITCH_LEFT;
2881 case EL_CONVEYOR_BELT4_SWITCH_MIDDLE:return GFX_BELT4_SWITCH_MIDDLE;
2882 case EL_CONVEYOR_BELT4_SWITCH_RIGHT:return GFX_BELT4_SWITCH_RIGHT;
2883 case EL_LANDMINE: return GFX_LANDMINE;
2884 case EL_ENVELOPE: return GFX_ENVELOPE;
2885 case EL_LIGHT_SWITCH: return GFX_LIGHT_SWITCH_OFF;
2886 case EL_LIGHT_SWITCH_ACTIVE: return GFX_LIGHT_SWITCH_ON;
2887 case EL_SIGN_EXCLAMATION: return GFX_SIGN_EXCLAMATION;
2888 case EL_SIGN_RADIOACTIVITY: return GFX_SIGN_RADIOACTIVITY;
2889 case EL_SIGN_STOP: return GFX_SIGN_STOP;
2890 case EL_SIGN_WHEELCHAIR: return GFX_SIGN_WHEELCHAIR;
2891 case EL_SIGN_PARKING: return GFX_SIGN_PARKING;
2892 case EL_SIGN_ONEWAY: return GFX_SIGN_ONEWAY;
2893 case EL_SIGN_HEART: return GFX_SIGN_HEART;
2894 case EL_SIGN_TRIANGLE: return GFX_SIGN_TRIANGLE;
2895 case EL_SIGN_ROUND: return GFX_SIGN_ROUND;
2896 case EL_SIGN_EXIT: return GFX_SIGN_EXIT;
2897 case EL_SIGN_YINYANG: return GFX_SIGN_YINYANG;
2898 case EL_SIGN_OTHER: return GFX_SIGN_OTHER;
2899 case EL_MOLE_LEFT: return GFX_MOLE_LEFT;
2900 case EL_MOLE_RIGHT: return GFX_MOLE_RIGHT;
2901 case EL_MOLE_UP: return GFX_MOLE_UP;
2902 case EL_MOLE_DOWN: return GFX_MOLE_DOWN;
2903 case EL_STEELWALL_SLANTED: return GFX_STEEL_SLANTED;
2904 case EL_INVISIBLE_SAND: return GFX_SAND_INVISIBLE;
2905 case EL_INVISIBLE_SAND_ACTIVE: return GFX_SAND_INVISIBLE_ON;
2906 case EL_DX_UNKNOWN_15: return GFX_DX_UNKNOWN_15;
2907 case EL_DX_UNKNOWN_42: return GFX_DX_UNKNOWN_42;
2908 case EL_TIMEGATE_OPEN: return GFX_TIMEGATE_OPEN;
2909 case EL_TIMEGATE_CLOSED: return GFX_TIMEGATE_CLOSED;
2910 case EL_TIMEGATE_SWITCH_ACTIVE: return GFX_TIMEGATE_SWITCH;
2911 case EL_TIMEGATE_SWITCH: return GFX_TIMEGATE_SWITCH;
2912 case EL_BALLOON: return GFX_BALLOON;
2913 case EL_BALLOON_SEND_LEFT: return GFX_BALLOON_SEND_LEFT;
2914 case EL_BALLOON_SEND_RIGHT: return GFX_BALLOON_SEND_RIGHT;
2915 case EL_BALLOON_SEND_UP: return GFX_BALLOON_SEND_UP;
2916 case EL_BALLOON_SEND_DOWN: return GFX_BALLOON_SEND_DOWN;
2917 case EL_BALLOON_SEND_ANY_DIRECTION: return GFX_BALLOON_SEND_ANY;
2918 case EL_EMC_STEELWALL1: return GFX_EMC_STEEL_WALL_1;
2919 case EL_EMC_STEELWALL2: return GFX_EMC_STEEL_WALL_2;
2920 case EL_EMC_STEELWALL3: return GFX_EMC_STEEL_WALL_3;
2921 case EL_EMC_STEELWALL4: return GFX_EMC_STEEL_WALL_4;
2922 case EL_EMC_WALL_PILLAR_UPPER: return GFX_EMC_WALL_1;
2923 case EL_EMC_WALL_PILLAR_MIDDLE: return GFX_EMC_WALL_2;
2924 case EL_EMC_WALL_PILLAR_LOWER: return GFX_EMC_WALL_3;
2925 case EL_EMC_WALL4: return GFX_EMC_WALL_4;
2926 case EL_EMC_WALL5: return GFX_EMC_WALL_5;
2927 case EL_EMC_WALL6: return GFX_EMC_WALL_6;
2928 case EL_EMC_WALL7: return GFX_EMC_WALL_7;
2929 case EL_EMC_WALL8: return GFX_EMC_WALL_8;
2930 case EL_TUBE_ALL: return GFX_TUBE_CROSS;
2931 case EL_TUBE_VERTICAL: return GFX_TUBE_VERTICAL;
2932 case EL_TUBE_HORIZONTAL: return GFX_TUBE_HORIZONTAL;
2933 case EL_TUBE_VERTICAL_LEFT: return GFX_TUBE_VERT_LEFT;
2934 case EL_TUBE_VERTICAL_RIGHT: return GFX_TUBE_VERT_RIGHT;
2935 case EL_TUBE_HORIZONTAL_UP: return GFX_TUBE_HORIZ_UP;
2936 case EL_TUBE_HORIZONTAL_DOWN: return GFX_TUBE_HORIZ_DOWN;
2937 case EL_TUBE_LEFT_UP: return GFX_TUBE_LEFT_UP;
2938 case EL_TUBE_LEFT_DOWN: return GFX_TUBE_LEFT_DOWN;
2939 case EL_TUBE_RIGHT_UP: return GFX_TUBE_RIGHT_UP;
2940 case EL_TUBE_RIGHT_DOWN: return GFX_TUBE_RIGHT_DOWN;
2941 case EL_SPRING: return GFX_SPRING;
2942 case EL_TRAP: return GFX_TRAP_INACTIVE;
2943 case EL_TRAP_ACTIVE: return GFX_TRAP_ACTIVE;
2944 case EL_BD_WALL: return GFX_BD_WALL;
2945 case EL_BD_ROCK: return GFX_BD_ROCK;
2946 case EL_DX_SUPABOMB: return GFX_DX_SUPABOMB;
2947 case EL_SP_MURPHY_CLONE: return GFX_SP_MURPHY_CLONE;
2951 if (IS_CHAR(element))
2952 return GFX_CHAR_START + (element - EL_CHAR_START);
2953 else if (element >= EL_SP_START && element <= EL_SP_END)
2955 int nr_element = element - EL_SP_START;
2956 int gfx_per_line = 8;
2958 (nr_element / gfx_per_line) * SP_PER_LINE +
2959 (nr_element % gfx_per_line);
2961 return GFX_START_ROCKSSP + nr_graphic;
2969 int el2gfx(int element)
2972 int graphic_OLD = el2gfx_OLD(element);
2977 int graphic_NEW = element_info[element].graphic[GFX_ACTION_DEFAULT];
2980 int graphic_OLD = el2gfx_OLD(element);
2982 if (element >= MAX_NUM_ELEMENTS)
2984 Error(ERR_WARN, "el2gfx: element == %d >= MAX_NUM_ELEMENTS", element);
2987 if (graphic_NEW != graphic_OLD)
2989 Error(ERR_WARN, "el2gfx: graphic_NEW (%d) != graphic_OLD (%d)",
2990 graphic_NEW, graphic_OLD);
2998 int el2img(int element)
3000 int graphic = element_info[element].graphic[GFX_ACTION_DEFAULT];
3004 Error(ERR_WARN, "element %d -> graphic %d -- probably crashing now...",
3011 int el_dir2img(int element, int direction)
3013 return el_dir_act2img(element, direction, GFX_ACTION_DEFAULT);
3016 int el_dir_act2img(int element, int direction, int action)
3021 printf("el_dir_act2img: THIS SHOULD NEVER HAPPEN: element == %d\n",
3029 printf("el_dir_act2img: THIS SHOULD NEVER HAPPEN: action == %d\n",
3036 action = graphics_action_mapping[action];
3037 direction = MV_DIR_BIT(direction);
3039 return element_info[element].direction_graphic[action][direction];