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 static int getGraphicAnimationPhase(int frames, int delay, int mode)
411 if (mode & ANIM_PINGPONG)
413 int max_anim_frames = 2 * frames - 2;
415 phase = (FrameCounter % (delay * max_anim_frames)) / delay;
416 phase = (phase < frames ? phase : max_anim_frames - phase);
419 phase = (FrameCounter % (delay * frames)) / delay;
421 if (mode & ANIM_REVERSE)
427 inline int getGraphicAnimationFrame(int graphic, int sync_frame)
429 /* animation synchronized with global frame counter, not move position */
430 if (new_graphic_info[graphic].anim_global_sync || sync_frame < 0)
431 sync_frame = FrameCounter;
433 return getAnimationFrame(new_graphic_info[graphic].anim_frames,
434 new_graphic_info[graphic].anim_delay,
435 new_graphic_info[graphic].anim_mode,
436 new_graphic_info[graphic].anim_start_frame,
440 void MarkTileDirty(int x, int y)
442 int xx = redraw_x1 + x;
443 int yy = redraw_y1 + y;
448 redraw[xx][yy] = TRUE;
449 redraw_mask |= REDRAW_TILES;
452 void SetBorderElement()
456 BorderElement = EL_EMPTY;
458 for(y=0; y<lev_fieldy && BorderElement == EL_EMPTY; y++)
460 for(x=0; x<lev_fieldx; x++)
462 if (!IS_MASSIVE(Feld[x][y]))
463 BorderElement = EL_STEELWALL;
465 if (y != 0 && y != lev_fieldy - 1 && x != lev_fieldx - 1)
471 void DrawAllPlayers()
475 for(i=0; i<MAX_PLAYERS; i++)
476 if (stored_player[i].active)
477 DrawPlayer(&stored_player[i]);
480 void DrawPlayerField(int x, int y)
482 if (!IS_PLAYER(x, y))
485 DrawPlayer(PLAYERINFO(x, y));
488 void DrawPlayer(struct PlayerInfo *player)
490 int jx = player->jx, jy = player->jy;
491 int last_jx = player->last_jx, last_jy = player->last_jy;
492 int next_jx = jx + (jx - last_jx), next_jy = jy + (jy - last_jy);
493 int sx = SCREENX(jx), sy = SCREENY(jy);
494 int sxx = 0, syy = 0;
495 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
498 boolean player_is_moving = (last_jx != jx || last_jy != jy ? TRUE : FALSE);
500 if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
504 if (!IN_LEV_FIELD(jx,jy))
506 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
507 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
508 printf("DrawPlayerField(): This should never happen!\n");
513 if (element == EL_EXPLOSION)
516 /* draw things in the field the player is leaving, if needed */
518 if (player_is_moving)
520 if (Store[last_jx][last_jy] && IS_DRAWABLE(last_element))
522 DrawLevelElement(last_jx, last_jy, Store[last_jx][last_jy]);
524 if (last_element == EL_DYNAMITE_ACTIVE)
525 DrawDynamite(last_jx, last_jy);
527 DrawLevelFieldThruMask(last_jx, last_jy);
529 else if (last_element == EL_DYNAMITE_ACTIVE)
530 DrawDynamite(last_jx, last_jy);
532 DrawLevelField(last_jx, last_jy);
534 if (player->Pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
538 if (Feld[next_jx][next_jy] == EL_SOKOBAN_FIELD_FULL)
539 DrawLevelElement(next_jx, next_jy, EL_SOKOBAN_FIELD_EMPTY);
541 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
544 DrawLevelField(next_jx, next_jy);
548 if (!IN_SCR_FIELD(sx, sy))
551 if (setup.direct_draw)
552 SetDrawtoField(DRAW_BUFFERED);
554 /* draw things behind the player, if needed */
557 DrawLevelElement(jx, jy, Store[jx][jy]);
558 else if (!IS_ACTIVE_BOMB(element))
559 DrawLevelField(jx, jy);
561 DrawLevelElement(jx, jy, EL_EMPTY);
563 /* draw player himself */
565 if (game.emulation == EMU_SUPAPLEX)
567 static int last_dir = MV_LEFT;
568 int action = (player->programmed_action ? player->programmed_action :
570 boolean action_moving =
572 ((action & (MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN)) &&
573 !(action & ~(MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN))));
575 graphic = IMG_SP_MURPHY;
579 if (player->MovDir == MV_LEFT)
580 graphic = IMG_SP_MURPHY_LEFT_PUSHING;
581 else if (player->MovDir == MV_RIGHT)
582 graphic = IMG_SP_MURPHY_RIGHT_PUSHING;
583 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
584 graphic = IMG_SP_MURPHY_LEFT_PUSHING;
585 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
586 graphic = IMG_SP_MURPHY_RIGHT_PUSHING;
588 else if (player->snapped)
590 if (player->MovDir == MV_LEFT)
591 graphic = IMG_SP_MURPHY_LEFT_SNAPPING;
592 else if (player->MovDir == MV_RIGHT)
593 graphic = IMG_SP_MURPHY_RIGHT_SNAPPING;
594 else if (player->MovDir == MV_UP)
595 graphic = IMG_SP_MURPHY_UP_SNAPPING;
596 else if (player->MovDir == MV_DOWN)
597 graphic = IMG_SP_MURPHY_DOWN_SNAPPING;
599 else if (action_moving)
601 if (player->MovDir == MV_LEFT)
602 graphic = IMG_SP_MURPHY_LEFT_MOVING;
603 else if (player->MovDir == MV_RIGHT)
604 graphic = IMG_SP_MURPHY_RIGHT_MOVING;
605 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
606 graphic = IMG_SP_MURPHY_LEFT_MOVING;
607 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
608 graphic = IMG_SP_MURPHY_RIGHT_MOVING;
610 graphic = IMG_SP_MURPHY_LEFT_MOVING;
612 frame = getGraphicAnimationFrame(graphic, -1);
615 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
616 last_dir = player->MovDir;
620 if (player->MovDir == MV_LEFT)
621 graphic = (player->Pushing ? IMG_PLAYER1_LEFT_PUSHING :
622 player->is_moving ? IMG_PLAYER1_LEFT_MOVING :
624 else if (player->MovDir == MV_RIGHT)
625 graphic = (player->Pushing ? IMG_PLAYER1_RIGHT_PUSHING :
626 player->is_moving ? IMG_PLAYER1_RIGHT_MOVING :
628 else if (player->MovDir == MV_UP)
629 graphic = (player->Pushing ? IMG_PLAYER1_UP_PUSHING :
630 player->is_moving ? IMG_PLAYER1_UP_MOVING :
632 else /* MV_DOWN || MV_NO_MOVING */
633 graphic = (player->Pushing ? IMG_PLAYER1_DOWN_PUSHING :
634 player->is_moving ? IMG_PLAYER1_DOWN_MOVING :
637 graphic = PLAYER_NR_GFX(graphic, player->index_nr);
640 frame = player->Frame;
642 frame = getGraphicAnimationFrame(graphic, player->Frame);
648 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
649 sxx = player->GfxPos;
651 syy = player->GfxPos;
654 if (!setup.soft_scrolling && ScreenMovPos)
659 printf("-> %d\n", player->Frame);
662 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
664 if (SHIELD_ON(player))
666 int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
667 IMG_SHIELD_NORMAL_ACTIVE);
668 int frame = getGraphicAnimationFrame(graphic, -1);
670 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
674 if (player->Pushing && player->GfxPos)
676 if (player->Pushing && player_is_moving)
679 int px = SCREENX(next_jx), py = SCREENY(next_jy);
682 (element == EL_SOKOBAN_FIELD_EMPTY ||
683 Feld[next_jx][next_jy] == EL_SOKOBAN_FIELD_FULL))
684 DrawGraphicShiftedThruMask(px, py, sxx, syy, IMG_SOKOBAN_OBJECT, 0,
688 int element = Feld[next_jx][next_jy];
689 int graphic = el2img(element);
694 if ((sxx || syy) && IS_PUSHABLE(element))
696 graphic = el_dir_act2img(element, player->MovDir, GFX_ACTION_MOVING);
698 frame = getGraphicAnimationFrame(graphic, player->GfxPos);
700 frame = getGraphicAnimationFrame(graphic, player->Frame);
704 printf("-> %d [%d]\n", player->Frame, player->GfxPos);
709 if (player->MovDir == MV_LEFT)
714 frame = (player->GfxPos / (TILEX / 4));
716 if (player->MovDir == MV_RIGHT)
717 frame = (frame + 4) % 4;
721 DrawGraphicShifted(px, py, sxx, syy, graphic, frame,
722 NO_CUTTING, NO_MASKING);
726 /* draw things in front of player (active dynamite or dynabombs) */
728 if (IS_ACTIVE_BOMB(element))
730 graphic = el2img(element);
733 if (element == EL_DYNAMITE_ACTIVE)
735 if ((frame = (96 - MovDelay[jx][jy]) / 12) > 6)
740 if ((frame = ((96 - MovDelay[jx][jy]) / 6) % 8) > 3)
744 frame = getGraphicAnimationFrame(graphic, 96 - MovDelay[jx][jy]);
747 if (game.emulation == EMU_SUPAPLEX)
748 DrawGraphic(sx, sy, IMG_SP_DISK_RED, 0);
750 DrawGraphicThruMask(sx, sy, graphic, frame);
753 if (player_is_moving && last_element == EL_EXPLOSION)
755 int stored = Store[last_jx][last_jy];
756 int graphic = (game.emulation != EMU_SUPAPLEX ? IMG_EXPLOSION :
757 stored == EL_SP_INFOTRON ? IMG_SP_EXPLOSION_INFOTRON :
759 int delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2);
760 int phase = ExplodePhase[last_jx][last_jy] - 1;
761 int frame = getGraphicAnimationFrame(graphic, phase - delay);
764 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy), graphic, frame);
767 /* draw elements that stay over the player */
768 /* handle the field the player is leaving ... */
769 if (player_is_moving && IS_OVER_PLAYER(last_element))
770 DrawLevelField(last_jx, last_jy);
772 /* ... and the field the player is entering */
773 if (IS_OVER_PLAYER(element))
774 DrawLevelField(jx, jy);
776 if (setup.direct_draw)
778 int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
779 int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
780 int x_size = TILEX * (1 + ABS(jx - last_jx));
781 int y_size = TILEY * (1 + ABS(jy - last_jy));
783 BlitBitmap(drawto_field, window,
784 dest_x, dest_y, x_size, y_size, dest_x, dest_y);
785 SetDrawtoField(DRAW_DIRECT);
788 MarkTileDirty(sx,sy);
791 inline void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
792 int graphic, int sync_frame, int mask_mode)
794 int frame = getGraphicAnimationFrame(graphic, sync_frame);
796 if (mask_mode == USE_MASKING)
797 DrawGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
799 DrawGraphicExt(dst_bitmap, x, y, graphic, frame);
802 inline void DrawGraphicAnimation(int x, int y, int graphic)
804 int lx = LEVELX(x), ly = LEVELY(y);
806 if (!IN_SCR_FIELD(x, y) ||
807 (GfxFrame[lx][ly] % new_graphic_info[graphic].anim_delay) != 0)
810 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
811 graphic, GfxFrame[lx][ly], NO_MASKING);
815 void DrawLevelGraphicAnimation(int x, int y, int graphic)
817 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
820 void DrawLevelElementAnimation(int x, int y, int element)
822 DrawGraphicAnimation(SCREENX(x), SCREENY(y), el2img(element));
826 void getOldGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
828 if (graphic >= 0 && graphic_info[graphic].bitmap != NULL)
830 *bitmap = graphic_info[graphic].bitmap;
831 *x = graphic_info[graphic].src_x;
832 *y = graphic_info[graphic].src_y;
834 else if (graphic >= GFX_START_ROCKSELEMENTS &&
835 graphic <= GFX_END_ROCKSELEMENTS)
837 graphic -= GFX_START_ROCKSELEMENTS;
838 *bitmap = new_graphic_info[IMG_OLD_PIX_ELEMENTS].bitmap;
839 *x = (graphic % GFX_PER_LINE) * TILEX;
840 *y = (graphic / GFX_PER_LINE) * TILEY;
842 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
844 graphic -= GFX_START_ROCKSHEROES;
845 *bitmap = new_graphic_info[IMG_OLD_PIX_HEROES].bitmap;
846 *x = (graphic % HEROES_PER_LINE) * TILEX;
847 *y = (graphic / HEROES_PER_LINE) * TILEY;
849 else if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
851 graphic -= GFX_START_ROCKSSP;
852 *bitmap = new_graphic_info[IMG_OLD_PIX_SP].bitmap;
853 *x = (graphic % SP_PER_LINE) * TILEX;
854 *y = (graphic / SP_PER_LINE) * TILEY;
856 else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
858 graphic -= GFX_START_ROCKSDC;
859 *bitmap = new_graphic_info[IMG_OLD_PIX_DC].bitmap;
860 *x = (graphic % DC_PER_LINE) * TILEX;
861 *y = (graphic / DC_PER_LINE) * TILEY;
863 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
865 graphic -= GFX_START_ROCKSMORE;
866 *bitmap = new_graphic_info[IMG_OLD_PIX_MORE].bitmap;
867 *x = (graphic % MORE_PER_LINE) * TILEX;
868 *y = (graphic / MORE_PER_LINE) * TILEY;
870 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
872 graphic -= GFX_START_ROCKSFONT;
873 *bitmap = new_graphic_info[IMG_OLD_PIX_FONT_EM].bitmap;
874 *x = (graphic % FONT_CHARS_PER_LINE) * TILEX;
875 *y = (graphic / FONT_CHARS_PER_LINE) * TILEY;
879 *bitmap = new_graphic_info[IMG_OLD_PIX_SP].bitmap;
886 void getGraphicSource(int graphic, int frame, Bitmap **bitmap, int *x, int *y)
888 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
889 int offset_x = new_graphic_info[graphic].offset_x;
890 int offset_y = new_graphic_info[graphic].offset_y;
891 int src_x = new_graphic_info[graphic].src_x + frame * offset_x;
892 int src_y = new_graphic_info[graphic].src_y + frame * offset_y;
894 *bitmap = src_bitmap;
899 void DrawGraphic(int x, int y, int graphic, int frame)
902 if (!IN_SCR_FIELD(x, y))
904 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
905 printf("DrawGraphic(): This should never happen!\n");
910 DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic, frame);
915 void DrawOldGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic)
920 getOldGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
921 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
925 void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
932 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
934 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
935 int src_x = new_graphic_info[graphic].src_x;
936 int src_y = new_graphic_info[graphic].src_y;
937 int offset_x = new_graphic_info[graphic].offset_x;
938 int offset_y = new_graphic_info[graphic].offset_y;
940 src_x += frame * offset_x;
941 src_y += frame * offset_y;
944 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
947 void DrawGraphicThruMask(int x, int y, int graphic, int frame)
950 if (!IN_SCR_FIELD(x, y))
952 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
953 printf("DrawGraphicThruMask(): This should never happen!\n");
958 DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY, graphic,
963 void DrawGraphicThruMaskExt(DrawBuffer *d, int dest_x, int dest_y, int graphic,
971 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
972 drawing_gc = src_bitmap->stored_clip_gc;
974 GC drawing_gc = src_bitmap->stored_clip_gc;
975 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
976 int src_x = new_graphic_info[graphic].src_x;
977 int src_y = new_graphic_info[graphic].src_y;
978 int offset_x = new_graphic_info[graphic].offset_x;
979 int offset_y = new_graphic_info[graphic].offset_y;
981 src_x += frame * offset_x;
982 src_y += frame * offset_y;
986 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
987 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dest_x, dest_y);
990 void DrawMiniGraphic(int x, int y, int graphic)
992 DrawMiniGraphicExt(drawto, SX + x * MINI_TILEX,SY + y * MINI_TILEY, graphic);
993 MarkTileDirty(x / 2, y / 2);
996 void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
998 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
1000 int mini_starty = src_bitmap->height * 2 / 3;
1001 int src_x = mini_startx + new_graphic_info[graphic].src_x / 2;
1002 int src_y = mini_starty + new_graphic_info[graphic].src_y / 2;
1004 if (src_x + MINI_TILEX > src_bitmap->width ||
1005 src_y + MINI_TILEY > src_bitmap->height)
1007 /* graphic of desired size seems not to be contained in this image;
1008 dirty workaround: get it from the middle of the normal sized image */
1010 getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
1011 src_x += (TILEX / 2 - MINI_TILEX / 2);
1012 src_y += (TILEY / 2 - MINI_TILEY / 2);
1015 *bitmap = src_bitmap;
1020 void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
1025 getMiniGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1026 BlitBitmap(src_bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
1029 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic, int frame,
1030 int cut_mode, int mask_mode)
1039 int width = TILEX, height = TILEY;
1045 DrawGraphic(x, y, graphic, frame);
1049 if (dx || dy) /* shifted graphic */
1051 if (x < BX1) /* object enters playfield from the left */
1058 else if (x > BX2) /* object enters playfield from the right */
1064 else if (x==BX1 && dx < 0) /* object leaves playfield to the left */
1070 else if (x==BX2 && dx > 0) /* object leaves playfield to the right */
1072 else if (dx) /* general horizontal movement */
1073 MarkTileDirty(x + SIGN(dx), y);
1075 if (y < BY1) /* object enters playfield from the top */
1077 if (cut_mode==CUT_BELOW) /* object completely above top border */
1085 else if (y > BY2) /* object enters playfield from the bottom */
1091 else if (y==BY1 && dy < 0) /* object leaves playfield to the top */
1097 else if (dy > 0 && cut_mode == CUT_ABOVE)
1099 if (y == BY2) /* object completely above bottom border */
1105 MarkTileDirty(x, y + 1);
1106 } /* object leaves playfield to the bottom */
1107 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1109 else if (dy) /* general vertical movement */
1110 MarkTileDirty(x, y + SIGN(dy));
1113 src_bitmap = new_graphic_info[graphic].bitmap;
1114 src_x = new_graphic_info[graphic].src_x;
1115 src_y = new_graphic_info[graphic].src_y;
1116 offset_x = new_graphic_info[graphic].offset_x;
1117 offset_y = new_graphic_info[graphic].offset_y;
1119 drawing_gc = src_bitmap->stored_clip_gc;
1121 src_x += frame * offset_x;
1122 src_y += frame * offset_y;
1127 dest_x = FX + x * TILEX + dx;
1128 dest_y = FY + y * TILEY + dy;
1131 if (!IN_SCR_FIELD(x,y))
1133 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1134 printf("DrawGraphicShifted(): This should never happen!\n");
1139 if (mask_mode == USE_MASKING)
1141 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1142 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
1146 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1152 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
1153 int frame, int cut_mode)
1155 DrawGraphicShifted(x,y, dx,dy, graphic, frame, cut_mode, USE_MASKING);
1159 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1160 int cut_mode, int mask_mode)
1162 int ux = LEVELX(x), uy = LEVELY(y);
1163 int graphic = el2gfx(element);
1164 int phase8 = ABS(MovPos[ux][uy]) / (TILEX / 8);
1165 int phase4 = phase8 / 2;
1166 int phase2 = phase8 / 4;
1167 int dir = MovDir[ux][uy];
1169 if (element == EL_PACMAN || element == EL_BUG || element == EL_SPACESHIP)
1171 graphic += 1 * !phase2;
1175 else if (dir == MV_LEFT)
1177 else if (dir == MV_DOWN)
1180 else if (element == EL_SP_SNIKSNAK)
1183 graphic = GFX_SP_SNIKSNAK_LEFT;
1184 else if (dir == MV_RIGHT)
1185 graphic = GFX_SP_SNIKSNAK_RIGHT;
1186 else if (dir == MV_UP)
1187 graphic = GFX_SP_SNIKSNAK_UP;
1189 graphic = GFX_SP_SNIKSNAK_DOWN;
1191 graphic += (phase8 < 4 ? phase8 : 7 - phase8);
1193 else if (element == EL_SP_ELECTRON)
1195 graphic = GFX2_SP_ELECTRON + getGraphicAnimationPhase(8, 2, ANIM_LOOP);
1197 else if (element == EL_MOLE || element == EL_PENGUIN ||
1198 element == EL_PIG || element == EL_DRAGON)
1201 graphic = (element == EL_MOLE ? GFX_MOLE_LEFT :
1202 element == EL_PENGUIN ? GFX_PINGUIN_LEFT :
1203 element == EL_PIG ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
1204 else if (dir == MV_RIGHT)
1205 graphic = (element == EL_MOLE ? GFX_MOLE_RIGHT :
1206 element == EL_PENGUIN ? GFX_PINGUIN_RIGHT :
1207 element == EL_PIG ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
1208 else if (dir == MV_UP)
1209 graphic = (element == EL_MOLE ? GFX_MOLE_UP :
1210 element == EL_PENGUIN ? GFX_PINGUIN_UP :
1211 element == EL_PIG ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
1213 graphic = (element == EL_MOLE ? GFX_MOLE_DOWN :
1214 element == EL_PENGUIN ? GFX_PINGUIN_DOWN :
1215 element == EL_PIG ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
1219 else if (element == EL_SATELLITE)
1221 graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_LOOP);
1223 else if (element == EL_ACID)
1225 graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_LOOP);
1227 else if (element == EL_BD_BUTTERFLY || element == EL_BD_FIREFLY)
1231 else if (element == EL_BALLOON)
1235 else if ((element == EL_ROCK ||
1236 element == EL_SP_ZONK ||
1237 element == EL_BD_ROCK ||
1238 element == EL_SP_INFOTRON ||
1242 if (uy >= lev_fieldy-1 || !IS_BELT(Feld[ux][uy+1]))
1244 if (element == EL_ROCK ||
1245 element == EL_SP_ZONK ||
1246 element == EL_BD_ROCK)
1249 graphic += (4 - phase4) % 4;
1250 else if (dir == MV_RIGHT)
1253 graphic += phase2 * 2;
1255 else if (element != EL_SP_INFOTRON)
1259 else if (element == EL_MAGIC_WALL_ACTIVE ||
1260 element == EL_MAGIC_WALL_EMPTYING ||
1261 element == EL_BD_MAGIC_WALL_ACTIVE ||
1262 element == EL_BD_MAGIC_WALL_EMPTYING ||
1263 element == EL_MAGIC_WALL_FULL ||
1264 element == EL_BD_MAGIC_WALL_FULL)
1266 graphic += 3 + getGraphicAnimationPhase(4, 4, ANIM_REVERSE);
1268 else if (IS_AMOEBOID(element) || element == EL_AMOEBA_DRIPPING)
1270 graphic = (element == EL_AMOEBA_DEAD ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
1271 graphic += (x + 2 * y + 4) % 4;
1273 else if (element == EL_WALL_GROWING)
1275 boolean links_massiv = FALSE, rechts_massiv = FALSE;
1277 if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
1278 links_massiv = TRUE;
1279 if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
1280 rechts_massiv = TRUE;
1282 if (links_massiv && rechts_massiv)
1283 graphic = GFX_MAUERWERK;
1284 else if (links_massiv)
1285 graphic = GFX_MAUER_R;
1286 else if (rechts_massiv)
1287 graphic = GFX_MAUER_L;
1290 else if ((element == EL_INVISIBLE_STEELWALL ||
1291 element == EL_INVISIBLE_WALL ||
1292 element == EL_INVISIBLE_SAND) && game.light_time_left)
1294 graphic = (element == EL_INVISIBLE_STEELWALL ? GFX_INVISIBLE_STEEL_ON :
1295 element == EL_INVISIBLE_WALL ? GFX_UNSICHTBAR_ON :
1296 GFX_SAND_INVISIBLE_ON);
1301 DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
1302 else if (mask_mode == USE_MASKING)
1303 DrawGraphicThruMask(x, y, graphic);
1305 DrawGraphic(x, y, graphic);
1309 inline static int getFramePosition(int x, int y)
1311 int frame_pos = -1; /* default: global synchronization */
1313 int element = Feld[x][y];
1315 if (element == EL_QUICKSAND_FULL ||
1316 element == EL_MAGIC_WALL_FULL ||
1317 element == EL_BD_MAGIC_WALL_FULL)
1319 else if (IS_MOVING(x, y) || CAN_MOVE(element) || CAN_FALL(element))
1320 frame_pos = ABS(MovPos[x][y]) / (TILEX / 8);
1323 frame_pos = ABS(MovPos[x][y]) / (TILEX / 8);
1325 frame_pos = GfxFrame[x][y];
1332 inline static int getGfxAction(int x, int y)
1334 int gfx_action = GFX_ACTION_DEFAULT;
1337 if (GfxAction[x][y] != GFX_ACTION_DEFAULT)
1338 gfx_action = GfxAction[x][y];
1339 else if (IS_MOVING(x, y))
1340 gfx_action = GFX_ACTION_MOVING;
1342 gfx_action = GfxAction[x][y];
1347 printf("getGfxAction: THIS SHOULD NEVER HAPPEN: GfxAction[%d][%d] == %d\n",
1354 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1355 int cut_mode, int mask_mode)
1357 int ux = LEVELX(x), uy = LEVELY(y);
1361 if (IN_LEV_FIELD(ux, uy))
1363 int move_dir = MovDir[ux][uy];
1364 int move_pos = getFramePosition(ux, uy);
1365 int gfx_action = getGfxAction(ux, uy);
1367 graphic = el_dir_act2img(element, move_dir, gfx_action);
1368 frame = getGraphicAnimationFrame(graphic, move_pos);
1372 graphic = el2img(element);
1373 frame = getGraphicAnimationFrame(graphic, 0);
1376 if (element == EL_WALL_GROWING)
1378 boolean left_stopped = FALSE, right_stopped = FALSE;
1380 if (!IN_LEV_FIELD(ux - 1, uy) || IS_MAUER(Feld[ux - 1][uy]))
1381 left_stopped = TRUE;
1382 if (!IN_LEV_FIELD(ux + 1, uy) || IS_MAUER(Feld[ux + 1][uy]))
1383 right_stopped = TRUE;
1385 if (left_stopped && right_stopped)
1387 else if (left_stopped)
1389 graphic = IMG_WALL_GROWING_ACTIVE_RIGHT;
1390 frame = new_graphic_info[graphic].anim_frames - 1;
1392 else if (right_stopped)
1394 graphic = IMG_WALL_GROWING_ACTIVE_LEFT;
1395 frame = new_graphic_info[graphic].anim_frames - 1;
1398 else if (IS_AMOEBOID(element) || element == EL_AMOEBA_DRIPPING)
1400 graphic = (element == EL_BD_AMOEBA ? IMG_BD_AMOEBA_PART1 :
1401 element == EL_AMOEBA_WET ? IMG_AMOEBA_WET_PART1 :
1402 element == EL_AMOEBA_DRY ? IMG_AMOEBA_DRY_PART1 :
1403 element == EL_AMOEBA_FULL ? IMG_AMOEBA_FULL_PART1 :
1404 IMG_AMOEBA_DEAD_PART1);
1406 graphic += (x + 2 * y + 4) % 4;
1410 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
1411 else if (mask_mode == USE_MASKING)
1412 DrawGraphicThruMask(x, y, graphic, frame);
1414 DrawGraphic(x, y, graphic, frame);
1417 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1418 int cut_mode, int mask_mode)
1420 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1421 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1422 cut_mode, mask_mode);
1425 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1428 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1431 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1434 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1438 void DrawOldScreenElementThruMask(int x, int y, int element)
1440 DrawOldScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1443 void DrawScreenElementThruMask(int x, int y, int element)
1445 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1449 void DrawLevelElementThruMask(int x, int y, int element)
1451 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1454 void DrawLevelFieldThruMask(int x, int y)
1456 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1459 void DrawCrumbledSand(int x, int y)
1463 int i, width, height, cx,cy;
1464 int ux = LEVELX(x), uy = LEVELY(y);
1465 int element, graphic;
1467 static int xy[4][2] =
1475 if (!IN_LEV_FIELD(ux, uy))
1478 element = Feld[ux][uy];
1480 if (element == EL_SAND ||
1481 element == EL_LANDMINE ||
1482 element == EL_TRAP ||
1483 element == EL_TRAP_ACTIVE)
1485 if (!IN_SCR_FIELD(x, y))
1488 graphic = IMG_SAND_CRUMBLED;
1490 src_bitmap = new_graphic_info[graphic].bitmap;
1491 src_x = new_graphic_info[graphic].src_x;
1492 src_y = new_graphic_info[graphic].src_y;
1498 uxx = ux + xy[i][0];
1499 uyy = uy + xy[i][1];
1500 if (!IN_LEV_FIELD(uxx, uyy))
1501 element = EL_STEELWALL;
1503 element = Feld[uxx][uyy];
1505 if (element == EL_SAND ||
1506 element == EL_LANDMINE ||
1507 element == EL_TRAP ||
1508 element == EL_TRAP_ACTIVE)
1511 if (i == 1 || i == 2)
1515 cx = (i == 2 ? TILEX - snip : 0);
1523 cy = (i == 3 ? TILEY - snip : 0);
1526 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1527 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1530 MarkTileDirty(x, y);
1534 graphic = IMG_SAND_CRUMBLED;
1536 src_bitmap = new_graphic_info[graphic].bitmap;
1537 src_x = new_graphic_info[graphic].src_x;
1538 src_y = new_graphic_info[graphic].src_y;
1542 int xx, yy, uxx, uyy;
1546 uxx = ux + xy[i][0];
1547 uyy = uy + xy[i][1];
1549 if (!IN_LEV_FIELD(uxx, uyy) ||
1550 (Feld[uxx][uyy] != EL_SAND &&
1551 Feld[uxx][uyy] != EL_LANDMINE &&
1552 Feld[uxx][uyy] != EL_TRAP &&
1553 Feld[uxx][uyy] != EL_TRAP_ACTIVE) ||
1554 !IN_SCR_FIELD(xx, yy))
1557 if (i == 1 || i == 2)
1561 cx = (i == 1 ? TILEX - snip : 0);
1569 cy = (i==0 ? TILEY-snip : 0);
1572 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1573 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1575 MarkTileDirty(xx, yy);
1580 void DrawScreenElement(int x, int y, int element)
1582 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1583 DrawCrumbledSand(x, y);
1586 void DrawLevelElement(int x, int y, int element)
1588 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1589 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1592 void DrawScreenField(int x, int y)
1594 int ux = LEVELX(x), uy = LEVELY(y);
1595 int element, content;
1597 if (!IN_LEV_FIELD(ux, uy))
1599 if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
1602 element = BorderElement;
1604 DrawScreenElement(x, y, element);
1608 element = Feld[ux][uy];
1609 content = Store[ux][uy];
1611 if (IS_MOVING(ux, uy))
1613 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1614 boolean cut_mode = NO_CUTTING;
1616 if (element == EL_QUICKSAND_EMPTYING ||
1617 element == EL_MAGIC_WALL_EMPTYING ||
1618 element == EL_BD_MAGIC_WALL_EMPTYING ||
1619 element == EL_AMOEBA_DRIPPING)
1620 cut_mode = CUT_ABOVE;
1621 else if (element == EL_QUICKSAND_FILLING ||
1622 element == EL_MAGIC_WALL_FILLING ||
1623 element == EL_BD_MAGIC_WALL_FILLING)
1624 cut_mode = CUT_BELOW;
1626 if (cut_mode == CUT_ABOVE)
1627 DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1629 DrawScreenElement(x, y, EL_EMPTY);
1632 DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1633 else if (cut_mode == NO_CUTTING)
1634 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1636 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], content, cut_mode);
1638 if (content == EL_ACID)
1639 DrawLevelElementThruMask(ux, uy + 1, EL_ACID);
1641 else if (IS_BLOCKED(ux, uy))
1646 boolean cut_mode = NO_CUTTING;
1647 int element_old, content_old;
1649 Blocked2Moving(ux, uy, &oldx, &oldy);
1652 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1653 MovDir[oldx][oldy] == MV_RIGHT);
1655 element_old = Feld[oldx][oldy];
1656 content_old = Store[oldx][oldy];
1658 if (element_old == EL_QUICKSAND_EMPTYING ||
1659 element_old == EL_MAGIC_WALL_EMPTYING ||
1660 element_old == EL_BD_MAGIC_WALL_EMPTYING ||
1661 element_old == EL_AMOEBA_DRIPPING)
1662 cut_mode = CUT_ABOVE;
1664 DrawScreenElement(x, y, EL_EMPTY);
1667 DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
1669 else if (cut_mode == NO_CUTTING)
1670 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
1673 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
1676 else if (IS_DRAWABLE(element))
1677 DrawScreenElement(x, y, element);
1679 DrawScreenElement(x, y, EL_EMPTY);
1682 void DrawLevelField(int x, int y)
1684 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1685 DrawScreenField(SCREENX(x), SCREENY(y));
1686 else if (IS_MOVING(x, y))
1690 Moving2Blocked(x, y, &newx, &newy);
1691 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1692 DrawScreenField(SCREENX(newx), SCREENY(newy));
1694 else if (IS_BLOCKED(x, y))
1698 Blocked2Moving(x, y, &oldx, &oldy);
1699 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1700 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1704 void DrawMiniElement(int x, int y, int element)
1708 graphic = el2img(element);
1709 DrawMiniGraphic(x, y, graphic);
1712 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1714 int x = sx + scroll_x, y = sy + scroll_y;
1716 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1717 DrawMiniElement(sx, sy, EL_EMPTY);
1718 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1719 DrawMiniElement(sx, sy, Feld[x][y]);
1722 int steel_type, steel_position;
1725 { IMG_STEELWALL_TOPLEFT, IMG_INVISIBLE_STEELWALL_TOPLEFT },
1726 { IMG_STEELWALL_TOPRIGHT, IMG_INVISIBLE_STEELWALL_TOPRIGHT },
1727 { IMG_STEELWALL_BOTTOMLEFT, IMG_INVISIBLE_STEELWALL_BOTTOMLEFT },
1728 { IMG_STEELWALL_BOTTOMRIGHT, IMG_INVISIBLE_STEELWALL_BOTTOMRIGHT },
1729 { IMG_STEELWALL_VERTICAL, IMG_INVISIBLE_STEELWALL_VERTICAL },
1730 { IMG_STEELWALL_HORIZONTAL, IMG_INVISIBLE_STEELWALL_HORIZONTAL }
1733 steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
1734 steel_position = (x == -1 && y == -1 ? 0 :
1735 x == lev_fieldx && y == -1 ? 1 :
1736 x == -1 && y == lev_fieldy ? 2 :
1737 x == lev_fieldx && y == lev_fieldy ? 3 :
1738 x == -1 || x == lev_fieldx ? 4 :
1739 y == -1 || y == lev_fieldy ? 5 : -1);
1741 if (steel_position != -1)
1742 DrawMiniGraphic(sx, sy, border[steel_position][steel_type]);
1746 void getMicroGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1748 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
1749 int mini_startx = src_bitmap->width * 3 / 4;
1750 int mini_starty = src_bitmap->height * 2 / 3;
1751 int src_x = mini_startx + new_graphic_info[graphic].src_x / 8;
1752 int src_y = mini_starty + new_graphic_info[graphic].src_y / 8;
1754 if (src_x + MICRO_TILEX > src_bitmap->width ||
1755 src_y + MICRO_TILEY > src_bitmap->height)
1757 /* graphic of desired size seems not to be contained in this image;
1758 dirty workaround: get it from the middle of the normal sized image */
1760 getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
1761 src_x += (TILEX / 2 - MICRO_TILEX / 2);
1762 src_y += (TILEY / 2 - MICRO_TILEY / 2);
1765 *bitmap = src_bitmap;
1770 void DrawMicroElement(int xpos, int ypos, int element)
1774 int graphic = el2img(element);
1776 getMicroGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1777 BlitBitmap(src_bitmap, drawto, src_x, src_y, MICRO_TILEX, MICRO_TILEY,
1785 SetDrawBackgroundMask(REDRAW_NONE);
1788 for(x=BX1; x<=BX2; x++)
1789 for(y=BY1; y<=BY2; y++)
1790 DrawScreenField(x, y);
1792 redraw_mask |= REDRAW_FIELD;
1795 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1799 for(x=0; x<size_x; x++)
1800 for(y=0; y<size_y; y++)
1801 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1803 redraw_mask |= REDRAW_FIELD;
1806 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1810 DrawBackground(xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
1812 if (lev_fieldx < STD_LEV_FIELDX)
1813 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1814 if (lev_fieldy < STD_LEV_FIELDY)
1815 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1817 xpos += MICRO_TILEX;
1818 ypos += MICRO_TILEY;
1820 for(x=-1; x<=STD_LEV_FIELDX; x++)
1822 for(y=-1; y<=STD_LEV_FIELDY; y++)
1824 int lx = from_x + x, ly = from_y + y;
1826 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1827 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1829 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1
1830 && BorderElement != EL_EMPTY)
1831 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1836 redraw_mask |= REDRAW_MICROLEVEL;
1839 #define MICROLABEL_EMPTY 0
1840 #define MICROLABEL_LEVEL_NAME 1
1841 #define MICROLABEL_CREATED_BY 2
1842 #define MICROLABEL_LEVEL_AUTHOR 3
1843 #define MICROLABEL_IMPORTED_FROM 4
1844 #define MICROLABEL_LEVEL_IMPORT_INFO 5
1846 #define MAX_MICROLABEL_SIZE (SXSIZE / FONT4_XSIZE)
1848 static void DrawMicroLevelLabelExt(int mode)
1850 char label_text[MAX_MICROLABEL_SIZE + 1];
1852 DrawBackground(SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
1854 strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
1855 mode == MICROLABEL_CREATED_BY ? "created by" :
1856 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
1857 mode == MICROLABEL_IMPORTED_FROM ? "imported from" :
1858 mode == MICROLABEL_LEVEL_IMPORT_INFO ?
1859 leveldir_current->imported_from : ""),
1860 MAX_MICROLABEL_SIZE);
1861 label_text[MAX_MICROLABEL_SIZE] = '\0';
1863 if (strlen(label_text) > 0)
1865 int lxpos = SX + (SXSIZE - strlen(label_text) * FONT4_XSIZE) / 2;
1866 int lypos = MICROLABEL_YPOS;
1868 DrawText(lxpos, lypos, label_text, FS_SMALL, FC_SPECIAL2);
1871 redraw_mask |= REDRAW_MICROLEVEL;
1874 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1876 static unsigned long scroll_delay = 0;
1877 static unsigned long label_delay = 0;
1878 static int from_x, from_y, scroll_direction;
1879 static int label_state, label_counter;
1883 from_x = from_y = 0;
1884 scroll_direction = MV_RIGHT;
1888 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1889 DrawMicroLevelLabelExt(label_state);
1891 /* initialize delay counters */
1892 DelayReached(&scroll_delay, 0);
1893 DelayReached(&label_delay, 0);
1898 /* scroll micro level, if needed */
1899 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1900 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1902 switch (scroll_direction)
1908 scroll_direction = MV_UP;
1912 if (from_x < lev_fieldx - STD_LEV_FIELDX)
1915 scroll_direction = MV_DOWN;
1922 scroll_direction = MV_RIGHT;
1926 if (from_y < lev_fieldy - STD_LEV_FIELDY)
1929 scroll_direction = MV_LEFT;
1936 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1939 /* redraw micro level label, if needed */
1940 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1941 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1942 strcmp(level.author, leveldir_current->name) != 0 &&
1943 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1945 int max_label_counter = 23;
1947 if (leveldir_current->imported_from != NULL)
1948 max_label_counter += 14;
1950 label_counter = (label_counter + 1) % max_label_counter;
1951 label_state = (label_counter >= 0 && label_counter <= 7 ?
1952 MICROLABEL_LEVEL_NAME :
1953 label_counter >= 9 && label_counter <= 12 ?
1954 MICROLABEL_CREATED_BY :
1955 label_counter >= 14 && label_counter <= 21 ?
1956 MICROLABEL_LEVEL_AUTHOR :
1957 label_counter >= 23 && label_counter <= 26 ?
1958 MICROLABEL_IMPORTED_FROM :
1959 label_counter >= 28 && label_counter <= 35 ?
1960 MICROLABEL_LEVEL_IMPORT_INFO : MICROLABEL_EMPTY);
1961 DrawMicroLevelLabelExt(label_state);
1965 int REQ_in_range(int x, int y)
1967 if (y > DY+249 && y < DY+278)
1969 if (x > DX+1 && x < DX+48)
1971 else if (x > DX+51 && x < DX+98)
1977 #define MAX_REQUEST_LINES 13
1978 #define MAX_REQUEST_LINE_LEN 7
1980 boolean Request(char *text, unsigned int req_state)
1982 int mx, my, ty, result = -1;
1983 unsigned int old_door_state;
1985 #if defined(PLATFORM_UNIX)
1986 /* pause network game while waiting for request to answer */
1987 if (options.network &&
1988 game_status == PLAYING &&
1989 req_state & REQUEST_WAIT_FOR)
1990 SendToServer_PausePlaying();
1993 old_door_state = GetDoorState();
1997 CloseDoor(DOOR_CLOSE_1);
1999 /* save old door content */
2000 BlitBitmap(bitmap_db_door, bitmap_db_door,
2001 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
2002 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
2004 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
2006 /* clear door drawing field */
2007 DrawBackground(DX, DY, DXSIZE, DYSIZE);
2009 /* write text for request */
2010 for(ty=0; ty < MAX_REQUEST_LINES; ty++)
2012 char text_line[MAX_REQUEST_LINE_LEN + 1];
2018 for(tl=0,tx=0; tx < MAX_REQUEST_LINE_LEN; tl++,tx++)
2021 if (!tc || tc == ' ')
2032 strncpy(text_line, text, tl);
2035 DrawText(DX + 50 - (tl * 14)/2, DY + 8 + ty * 16,
2036 text_line, FS_SMALL, FC_YELLOW);
2038 text += tl + (tc == ' ' ? 1 : 0);
2041 if (req_state & REQ_ASK)
2043 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
2044 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
2046 else if (req_state & REQ_CONFIRM)
2048 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
2050 else if (req_state & REQ_PLAYER)
2052 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
2053 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
2054 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
2055 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
2058 /* copy request gadgets to door backbuffer */
2059 BlitBitmap(drawto, bitmap_db_door,
2060 DX, DY, DXSIZE, DYSIZE,
2061 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2063 OpenDoor(DOOR_OPEN_1);
2069 if (!(req_state & REQUEST_WAIT_FOR))
2071 SetDrawBackgroundMask(REDRAW_FIELD);
2076 if (game_status != MAINMENU)
2079 button_status = MB_RELEASED;
2081 request_gadget_id = -1;
2083 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
2095 case EVENT_BUTTONPRESS:
2096 case EVENT_BUTTONRELEASE:
2097 case EVENT_MOTIONNOTIFY:
2099 if (event.type == EVENT_MOTIONNOTIFY)
2101 if (!PointerInWindow(window))
2102 continue; /* window and pointer are on different screens */
2107 motion_status = TRUE;
2108 mx = ((MotionEvent *) &event)->x;
2109 my = ((MotionEvent *) &event)->y;
2113 motion_status = FALSE;
2114 mx = ((ButtonEvent *) &event)->x;
2115 my = ((ButtonEvent *) &event)->y;
2116 if (event.type == EVENT_BUTTONPRESS)
2117 button_status = ((ButtonEvent *) &event)->button;
2119 button_status = MB_RELEASED;
2122 /* this sets 'request_gadget_id' */
2123 HandleGadgets(mx, my, button_status);
2125 switch(request_gadget_id)
2127 case TOOL_CTRL_ID_YES:
2130 case TOOL_CTRL_ID_NO:
2133 case TOOL_CTRL_ID_CONFIRM:
2134 result = TRUE | FALSE;
2137 case TOOL_CTRL_ID_PLAYER_1:
2140 case TOOL_CTRL_ID_PLAYER_2:
2143 case TOOL_CTRL_ID_PLAYER_3:
2146 case TOOL_CTRL_ID_PLAYER_4:
2157 case EVENT_KEYPRESS:
2158 switch(GetEventKey((KeyEvent *)&event, TRUE))
2171 if (req_state & REQ_PLAYER)
2175 case EVENT_KEYRELEASE:
2176 ClearPlayerAction();
2180 HandleOtherEvents(&event);
2184 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2186 int joy = AnyJoystick();
2188 if (joy & JOY_BUTTON_1)
2190 else if (joy & JOY_BUTTON_2)
2196 /* don't eat all CPU time */
2200 if (game_status != MAINMENU)
2205 if (!(req_state & REQ_STAY_OPEN))
2207 CloseDoor(DOOR_CLOSE_1);
2209 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
2211 BlitBitmap(bitmap_db_door, bitmap_db_door,
2212 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
2213 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
2214 OpenDoor(DOOR_OPEN_1);
2220 SetDrawBackgroundMask(REDRAW_FIELD);
2222 #if defined(PLATFORM_UNIX)
2223 /* continue network game after request */
2224 if (options.network &&
2225 game_status == PLAYING &&
2226 req_state & REQUEST_WAIT_FOR)
2227 SendToServer_ContinuePlaying();
2233 unsigned int OpenDoor(unsigned int door_state)
2235 unsigned int new_door_state;
2237 if (door_state & DOOR_COPY_BACK)
2239 BlitBitmap(bitmap_db_door, bitmap_db_door,
2240 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
2241 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2242 door_state &= ~DOOR_COPY_BACK;
2245 new_door_state = MoveDoor(door_state);
2247 return(new_door_state);
2250 unsigned int CloseDoor(unsigned int door_state)
2252 unsigned int new_door_state;
2254 BlitBitmap(backbuffer, bitmap_db_door,
2255 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2256 BlitBitmap(backbuffer, bitmap_db_door,
2257 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2259 new_door_state = MoveDoor(door_state);
2261 return(new_door_state);
2264 unsigned int GetDoorState()
2266 return MoveDoor(DOOR_GET_STATE);
2269 unsigned int SetDoorState(unsigned int door_state)
2271 return MoveDoor(door_state | DOOR_SET_STATE);
2274 unsigned int MoveDoor(unsigned int door_state)
2276 static int door1 = DOOR_OPEN_1;
2277 static int door2 = DOOR_CLOSE_2;
2278 static unsigned long door_delay = 0;
2279 int x, start, stepsize = 2;
2280 unsigned long door_delay_value = stepsize * 5;
2282 if (door_state == DOOR_GET_STATE)
2283 return(door1 | door2);
2285 if (door_state & DOOR_SET_STATE)
2287 if (door_state & DOOR_ACTION_1)
2288 door1 = door_state & DOOR_ACTION_1;
2289 if (door_state & DOOR_ACTION_2)
2290 door2 = door_state & DOOR_ACTION_2;
2292 return(door1 | door2);
2295 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2296 door_state &= ~DOOR_OPEN_1;
2297 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2298 door_state &= ~DOOR_CLOSE_1;
2299 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2300 door_state &= ~DOOR_OPEN_2;
2301 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2302 door_state &= ~DOOR_CLOSE_2;
2304 if (setup.quick_doors)
2307 door_delay_value = 0;
2309 StopSound(SND_MENU_DOOR_OPENING);
2310 StopSound(SND_MENU_DOOR_CLOSING);
2313 if (global.autoplay_leveldir)
2315 door_state |= DOOR_NO_DELAY;
2316 door_state &= ~DOOR_CLOSE_ALL;
2319 if (door_state & DOOR_ACTION)
2321 if (!(door_state & DOOR_NO_DELAY))
2323 /* opening door sound has priority over simultaneously closing door */
2324 if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
2325 PlaySoundStereo(SND_MENU_DOOR_OPENING, SOUND_MAX_RIGHT);
2326 else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
2327 PlaySoundStereo(SND_MENU_DOOR_CLOSING, SOUND_MAX_RIGHT);
2330 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2332 for(x=start; x<=DXSIZE; x+=stepsize)
2334 Bitmap *bitmap = new_graphic_info[IMG_GLOBAL_DOOR].bitmap;
2335 GC gc = bitmap->stored_clip_gc;
2337 if (!(door_state & DOOR_NO_DELAY))
2338 WaitUntilDelayReached(&door_delay, door_delay_value);
2340 if (door_state & DOOR_ACTION_1)
2342 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
2343 int j = (DXSIZE - i) / 3;
2345 BlitBitmap(bitmap_db_door, drawto,
2346 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
2347 DXSIZE,DYSIZE - i/2, DX, DY);
2349 ClearRectangle(drawto, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
2351 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2352 BlitBitmapMasked(bitmap, drawto,
2353 DXSIZE, DOOR_GFX_PAGEY1, i, 77,
2354 DX + DXSIZE - i, DY + j);
2355 BlitBitmapMasked(bitmap, drawto,
2356 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
2357 DX + DXSIZE - i, DY + 140 + j);
2358 SetClipOrigin(bitmap, gc, DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
2359 BlitBitmapMasked(bitmap, drawto,
2360 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
2362 BlitBitmapMasked(bitmap, drawto,
2363 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
2366 BlitBitmapMasked(bitmap, drawto,
2367 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2369 BlitBitmapMasked(bitmap, drawto,
2370 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2372 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2373 BlitBitmapMasked(bitmap, drawto,
2374 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2375 DX + DXSIZE - i, DY + 77 + j);
2376 BlitBitmapMasked(bitmap, drawto,
2377 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2378 DX + DXSIZE - i, DY + 203 + j);
2380 redraw_mask |= REDRAW_DOOR_1;
2383 if (door_state & DOOR_ACTION_2)
2385 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
2386 int j = (VXSIZE - i) / 3;
2388 BlitBitmap(bitmap_db_door, drawto,
2389 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
2390 VXSIZE, VYSIZE - i/2, VX, VY);
2392 ClearRectangle(drawto, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
2394 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2395 BlitBitmapMasked(bitmap, drawto,
2396 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
2397 VX + VXSIZE-i, VY+j);
2398 SetClipOrigin(bitmap, gc,
2399 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2400 BlitBitmapMasked(bitmap, drawto,
2401 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
2404 BlitBitmapMasked(bitmap, drawto,
2405 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2406 i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
2407 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2408 BlitBitmapMasked(bitmap, drawto,
2409 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2411 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2413 redraw_mask |= REDRAW_DOOR_2;
2418 if (game_status == MAINMENU)
2423 if (setup.quick_doors)
2425 StopSound(SND_MENU_DOOR_OPENING);
2426 StopSound(SND_MENU_DOOR_CLOSING);
2429 if (door_state & DOOR_ACTION_1)
2430 door1 = door_state & DOOR_ACTION_1;
2431 if (door_state & DOOR_ACTION_2)
2432 door2 = door_state & DOOR_ACTION_2;
2434 return (door1 | door2);
2437 void DrawSpecialEditorDoor()
2439 /* draw bigger toolbox window */
2440 BlitBitmap(new_graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
2441 DOOR_GFX_PAGEX7, 0, EXSIZE + 8, 8,
2443 BlitBitmap(new_graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2444 EX - 4, VY - 4, EXSIZE + 8, EYSIZE - VYSIZE + 4,
2447 redraw_mask |= REDRAW_ALL;
2450 void UndrawSpecialEditorDoor()
2452 /* draw normal tape recorder window */
2453 BlitBitmap(new_graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2454 EX - 4, EY - 12, EXSIZE + 8, EYSIZE - VYSIZE + 12,
2457 redraw_mask |= REDRAW_ALL;
2461 int ReadPixel(DrawBuffer *bitmap, int x, int y)
2463 XImage *pixel_image;
2464 unsigned long pixel_value;
2466 pixel_image = XGetImage(display, bitmap->drawable,
2467 x, y, 1, 1, AllPlanes, ZPixmap);
2468 pixel_value = XGetPixel(pixel_image, 0, 0);
2470 XDestroyImage(pixel_image);
2476 /* ---------- new tool button stuff ---------------------------------------- */
2478 /* graphic position values for tool buttons */
2479 #define TOOL_BUTTON_YES_XPOS 2
2480 #define TOOL_BUTTON_YES_YPOS 250
2481 #define TOOL_BUTTON_YES_GFX_YPOS 0
2482 #define TOOL_BUTTON_YES_XSIZE 46
2483 #define TOOL_BUTTON_YES_YSIZE 28
2484 #define TOOL_BUTTON_NO_XPOS 52
2485 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2486 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2487 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2488 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2489 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2490 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2491 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2492 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2493 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2494 #define TOOL_BUTTON_PLAYER_XSIZE 30
2495 #define TOOL_BUTTON_PLAYER_YSIZE 30
2496 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2497 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2498 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2499 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2500 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2501 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2502 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2503 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2504 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2505 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2506 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2507 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2508 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2509 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2510 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2511 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2512 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2513 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2514 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2515 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2524 } toolbutton_info[NUM_TOOL_BUTTONS] =
2527 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2528 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2529 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2534 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2535 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2536 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2541 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2542 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2543 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2544 TOOL_CTRL_ID_CONFIRM,
2548 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2549 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2550 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2551 TOOL_CTRL_ID_PLAYER_1,
2555 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2556 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2557 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2558 TOOL_CTRL_ID_PLAYER_2,
2562 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2563 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2564 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2565 TOOL_CTRL_ID_PLAYER_3,
2569 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2570 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2571 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2572 TOOL_CTRL_ID_PLAYER_4,
2577 void CreateToolButtons()
2581 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2583 Bitmap *gd_bitmap = new_graphic_info[IMG_GLOBAL_DOOR].bitmap;
2584 Bitmap *deco_bitmap = None;
2585 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2586 struct GadgetInfo *gi;
2587 unsigned long event_mask;
2588 int gd_xoffset, gd_yoffset;
2589 int gd_x1, gd_x2, gd_y;
2592 event_mask = GD_EVENT_RELEASED;
2594 gd_xoffset = toolbutton_info[i].xpos;
2595 gd_yoffset = toolbutton_info[i].ypos;
2596 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2597 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2598 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2600 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2602 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
2604 getMiniGraphicSource(PLAYER_NR_GFX(IMG_PLAYER1, player_nr),
2605 &deco_bitmap, &deco_x, &deco_y);
2606 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2607 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2610 gi = CreateGadget(GDI_CUSTOM_ID, id,
2611 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2612 GDI_X, DX + toolbutton_info[i].x,
2613 GDI_Y, DY + toolbutton_info[i].y,
2614 GDI_WIDTH, toolbutton_info[i].width,
2615 GDI_HEIGHT, toolbutton_info[i].height,
2616 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2617 GDI_STATE, GD_BUTTON_UNPRESSED,
2618 GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
2619 GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
2620 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
2621 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2622 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2623 GDI_DECORATION_SHIFTING, 1, 1,
2624 GDI_EVENT_MASK, event_mask,
2625 GDI_CALLBACK_ACTION, HandleToolButtons,
2629 Error(ERR_EXIT, "cannot create gadget");
2631 tool_gadget[id] = gi;
2635 void FreeToolButtons()
2639 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2640 FreeGadget(tool_gadget[i]);
2643 static void UnmapToolButtons()
2647 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2648 UnmapGadget(tool_gadget[i]);
2651 static void HandleToolButtons(struct GadgetInfo *gi)
2653 request_gadget_id = gi->custom_id;
2656 int get_next_element(int element)
2660 case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL;
2661 case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY;
2662 case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL;
2663 case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_ACTIVE;
2664 case EL_BD_MAGIC_WALL_FILLING: return EL_BD_MAGIC_WALL_FULL;
2665 case EL_BD_MAGIC_WALL_EMPTYING: return EL_BD_MAGIC_WALL_ACTIVE;
2666 case EL_AMOEBA_DRIPPING: return EL_AMOEBA_WET;
2668 default: return element;
2672 int el2gfx_OLD(int element)
2676 case EL_EMPTY: return -1;
2677 case EL_SAND: return GFX_ERDREICH;
2678 case EL_WALL: return GFX_MAUERWERK;
2679 case EL_WALL_CRUMBLED: return GFX_FELSBODEN;
2680 case EL_ROCK: return GFX_FELSBROCKEN;
2681 case EL_EMERALD: return GFX_EDELSTEIN;
2682 case EL_EXIT_CLOSED: return GFX_AUSGANG_ZU;
2683 case EL_EXIT_OPENING: return GFX_AUSGANG_ACT;
2684 case EL_EXIT_OPEN: return GFX_AUSGANG_AUF;
2685 case EL_SP_EXIT_OPEN: return GFX_SP_EXIT;
2686 case EL_PLAYER1: return GFX_SPIELER1;
2687 case EL_PLAYER2: return GFX_SPIELER2;
2688 case EL_PLAYER3: return GFX_SPIELER3;
2689 case EL_PLAYER4: return GFX_SPIELER4;
2690 case EL_BUG: return GFX_KAEFER;
2691 case EL_BUG_RIGHT: return GFX_KAEFER_RIGHT;
2692 case EL_BUG_UP: return GFX_KAEFER_UP;
2693 case EL_BUG_LEFT: return GFX_KAEFER_LEFT;
2694 case EL_BUG_DOWN: return GFX_KAEFER_DOWN;
2695 case EL_SPACESHIP: return GFX_FLIEGER;
2696 case EL_SPACESHIP_RIGHT: return GFX_FLIEGER_RIGHT;
2697 case EL_SPACESHIP_UP: return GFX_FLIEGER_UP;
2698 case EL_SPACESHIP_LEFT: return GFX_FLIEGER_LEFT;
2699 case EL_SPACESHIP_DOWN: return GFX_FLIEGER_DOWN;
2700 case EL_BD_BUTTERFLY: return GFX_BUTTERFLY;
2701 case EL_BD_BUTTERFLY_RIGHT: return GFX_BUTTERFLY_RIGHT;
2702 case EL_BD_BUTTERFLY_UP: return GFX_BUTTERFLY_UP;
2703 case EL_BD_BUTTERFLY_LEFT: return GFX_BUTTERFLY_LEFT;
2704 case EL_BD_BUTTERFLY_DOWN: return GFX_BUTTERFLY_DOWN;
2705 case EL_BD_FIREFLY: return GFX_FIREFLY;
2706 case EL_BD_FIREFLY_RIGHT: return GFX_FIREFLY_RIGHT;
2707 case EL_BD_FIREFLY_UP: return GFX_FIREFLY_UP;
2708 case EL_BD_FIREFLY_LEFT: return GFX_FIREFLY_LEFT;
2709 case EL_BD_FIREFLY_DOWN: return GFX_FIREFLY_DOWN;
2710 case EL_YAMYAM: return GFX_MAMPFER;
2711 case EL_ROBOT: return GFX_ROBOT;
2712 case EL_STEELWALL: return GFX_BETON;
2713 case EL_DIAMOND: return GFX_DIAMANT;
2714 case EL_QUICKSAND_EMPTY: return GFX_MORAST_LEER;
2715 case EL_QUICKSAND_FULL: return GFX_MORAST_VOLL;
2716 case EL_QUICKSAND_EMPTYING: return GFX_MORAST_LEER;
2717 case EL_AMOEBA_DROP: return GFX_TROPFEN;
2718 case EL_BOMB: return GFX_BOMBE;
2719 case EL_MAGIC_WALL: return GFX_MAGIC_WALL_OFF;
2720 case EL_MAGIC_WALL_ACTIVE: return GFX_MAGIC_WALL_EMPTY;
2721 case EL_MAGIC_WALL_EMPTYING: return GFX_MAGIC_WALL_EMPTY;
2722 case EL_MAGIC_WALL_FULL: return GFX_MAGIC_WALL_FULL;
2723 case EL_MAGIC_WALL_DEAD: return GFX_MAGIC_WALL_DEAD;
2724 case EL_ACID: return GFX_SALZSAEURE;
2725 case EL_AMOEBA_DEAD: return GFX_AMOEBE_TOT;
2726 case EL_AMOEBA_WET: return GFX_AMOEBE_NASS;
2727 case EL_AMOEBA_DRY: return GFX_AMOEBE_NORM;
2728 case EL_AMOEBA_FULL: return GFX_AMOEBE_VOLL;
2729 case EL_BD_AMOEBA: return GFX_AMOEBE_BD;
2730 case EL_AMOEBA_TO_DIAMOND: return GFX_AMOEBA2DIAM;
2731 case EL_AMOEBA_DRIPPING: return GFX_AMOEBE_NASS;
2732 case EL_NUT: return GFX_KOKOSNUSS;
2733 case EL_GAMEOFLIFE: return GFX_LIFE;
2734 case EL_BIOMAZE: return GFX_LIFE_ASYNC;
2735 case EL_DYNAMITE_ACTIVE: return GFX_DYNAMIT;
2736 case EL_STONEBLOCK: return GFX_BADEWANNE;
2737 case EL_ACIDPOOL_TOPLEFT: return GFX_BADEWANNE1;
2738 case EL_ACIDPOOL_TOPRIGHT: return GFX_BADEWANNE2;
2739 case EL_ACIDPOOL_BOTTOMLEFT: return GFX_BADEWANNE3;
2740 case EL_ACIDPOOL_BOTTOM: return GFX_BADEWANNE4;
2741 case EL_ACIDPOOL_BOTTOMRIGHT: return GFX_BADEWANNE5;
2742 case EL_ROBOT_WHEEL: return GFX_ABLENK_AUS;
2743 case EL_ROBOT_WHEEL_ACTIVE: return GFX_ABLENK_EIN;
2744 case EL_KEY1: return GFX_SCHLUESSEL1;
2745 case EL_KEY2: return GFX_SCHLUESSEL2;
2746 case EL_KEY3: return GFX_SCHLUESSEL3;
2747 case EL_KEY4: return GFX_SCHLUESSEL4;
2748 case EL_GATE1: return GFX_PFORTE1;
2749 case EL_GATE2: return GFX_PFORTE2;
2750 case EL_GATE3: return GFX_PFORTE3;
2751 case EL_GATE4: return GFX_PFORTE4;
2752 case EL_GATE1_GRAY: return GFX_PFORTE1X;
2753 case EL_GATE2_GRAY: return GFX_PFORTE2X;
2754 case EL_GATE3_GRAY: return GFX_PFORTE3X;
2755 case EL_GATE4_GRAY: return GFX_PFORTE4X;
2756 case EL_DYNAMITE: return GFX_DYNAMIT_AUS;
2757 case EL_PACMAN: return GFX_PACMAN;
2758 case EL_PACMAN_RIGHT: return GFX_PACMAN_RIGHT;
2759 case EL_PACMAN_UP: return GFX_PACMAN_UP;
2760 case EL_PACMAN_LEFT: return GFX_PACMAN_LEFT;
2761 case EL_PACMAN_DOWN: return GFX_PACMAN_DOWN;
2762 case EL_INVISIBLE_WALL: return GFX_UNSICHTBAR;
2763 case EL_INVISIBLE_WALL_ACTIVE: return GFX_UNSICHTBAR_ON;
2764 case EL_WALL_EMERALD: return GFX_ERZ_EDEL;
2765 case EL_WALL_DIAMOND: return GFX_ERZ_DIAM;
2766 case EL_LAMP: return GFX_BIRNE_AUS;
2767 case EL_LAMP_ACTIVE: return GFX_BIRNE_EIN;
2768 case EL_TIME_ORB_FULL: return GFX_ZEIT_VOLL;
2769 case EL_TIME_ORB_EMPTY: return GFX_ZEIT_LEER;
2770 case EL_WALL_GROWING: return GFX_MAUER_LEBT;
2771 case EL_WALL_GROWING_X: return GFX_MAUER_X;
2772 case EL_WALL_GROWING_Y: return GFX_MAUER_Y;
2773 case EL_WALL_GROWING_XY: return GFX_MAUER_XY;
2774 case EL_BD_DIAMOND: return GFX_EDELSTEIN_BD;
2775 case EL_EMERALD_YELLOW: return GFX_EDELSTEIN_GELB;
2776 case EL_EMERALD_RED: return GFX_EDELSTEIN_ROT;
2777 case EL_EMERALD_PURPLE: return GFX_EDELSTEIN_LILA;
2778 case EL_WALL_BD_DIAMOND: return GFX_ERZ_EDEL_BD;
2779 case EL_WALL_EMERALD_YELLOW: return GFX_ERZ_EDEL_GELB;
2780 case EL_WALL_EMERALD_RED: return GFX_ERZ_EDEL_ROT;
2781 case EL_WALL_EMERALD_PURPLE: return GFX_ERZ_EDEL_LILA;
2782 case EL_DARK_YAMYAM: return GFX_MAMPFER2;
2783 case EL_BD_MAGIC_WALL: return GFX_MAGIC_WALL_BD_OFF;
2784 case EL_BD_MAGIC_WALL_ACTIVE: return GFX_MAGIC_WALL_BD_EMPTY;
2785 case EL_BD_MAGIC_WALL_EMPTYING: return GFX_MAGIC_WALL_BD_EMPTY;
2786 case EL_BD_MAGIC_WALL_FULL: return GFX_MAGIC_WALL_BD_FULL;
2787 case EL_BD_MAGIC_WALL_DEAD: return GFX_MAGIC_WALL_BD_DEAD;
2788 case EL_DYNABOMB_PLAYER1_ACTIVE: return GFX_DYNABOMB;
2789 case EL_DYNABOMB_PLAYER2_ACTIVE: return GFX_DYNABOMB;
2790 case EL_DYNABOMB_PLAYER3_ACTIVE: return GFX_DYNABOMB;
2791 case EL_DYNABOMB_PLAYER4_ACTIVE: return GFX_DYNABOMB;
2792 case EL_DYNABOMB_NR: return GFX_DYNABOMB_NR;
2793 case EL_DYNABOMB_SZ: return GFX_DYNABOMB_SZ;
2794 case EL_DYNABOMB_XL: return GFX_DYNABOMB_XL;
2795 case EL_SOKOBAN_OBJECT: return GFX_SOKOBAN_OBJEKT;
2796 case EL_SOKOBAN_FIELD_EMPTY: return GFX_SOKOBAN_FELD_LEER;
2797 case EL_SOKOBAN_FIELD_FULL: return GFX_SOKOBAN_FELD_VOLL;
2798 case EL_MOLE: return GFX_MOLE;
2799 case EL_PENGUIN: return GFX_PINGUIN;
2800 case EL_PIG: return GFX_SCHWEIN;
2801 case EL_DRAGON: return GFX_DRACHE;
2802 case EL_SATELLITE: return GFX_SONDE;
2803 case EL_ARROW_BLUE_LEFT: return GFX_PFEIL_LEFT;
2804 case EL_ARROW_BLUE_RIGHT: return GFX_PFEIL_RIGHT;
2805 case EL_ARROW_BLUE_UP: return GFX_PFEIL_UP;
2806 case EL_ARROW_BLUE_DOWN: return GFX_PFEIL_DOWN;
2807 case EL_SPEED_PILL: return GFX_SPEED_PILL;
2808 case EL_SP_TERMINAL_ACTIVE: return GFX_SP_TERMINAL;
2809 case EL_SP_BUGGY_BASE_ACTIVE: return GFX_SP_BUG_ACTIVE;
2810 case EL_SP_ZONK: return GFX_SP_ZONK;
2811 /* ^^^^^^^^^^ non-standard position in supaplex graphic set! */
2812 case EL_INVISIBLE_STEELWALL: return GFX_INVISIBLE_STEEL;
2813 case EL_INVISIBLE_STEELWALL_ACTIVE: return GFX_INVISIBLE_STEEL_ON;
2814 case EL_BLACK_ORB: return GFX_BLACK_ORB;
2815 case EL_EM_GATE1: return GFX_EM_GATE_1;
2816 case EL_EM_GATE2: return GFX_EM_GATE_2;
2817 case EL_EM_GATE3: return GFX_EM_GATE_3;
2818 case EL_EM_GATE4: return GFX_EM_GATE_4;
2819 case EL_EM_GATE1_GRAY: return GFX_EM_GATE_1X;
2820 case EL_EM_GATE2_GRAY: return GFX_EM_GATE_2X;
2821 case EL_EM_GATE3_GRAY: return GFX_EM_GATE_3X;
2822 case EL_EM_GATE4_GRAY: return GFX_EM_GATE_4X;
2823 case EL_EM_KEY1_FILE: return GFX_EM_KEY_1;
2824 case EL_EM_KEY2_FILE: return GFX_EM_KEY_2;
2825 case EL_EM_KEY3_FILE: return GFX_EM_KEY_3;
2826 case EL_EM_KEY4_FILE: return GFX_EM_KEY_4;
2827 case EL_EM_KEY1: return GFX_EM_KEY_1;
2828 case EL_EM_KEY2: return GFX_EM_KEY_2;
2829 case EL_EM_KEY3: return GFX_EM_KEY_3;
2830 case EL_EM_KEY4: return GFX_EM_KEY_4;
2831 case EL_PEARL: return GFX_PEARL;
2832 case EL_CRYSTAL: return GFX_CRYSTAL;
2833 case EL_WALL_PEARL: return GFX_WALL_PEARL;
2834 case EL_WALL_CRYSTAL: return GFX_WALL_CRYSTAL;
2835 case EL_DOOR_WHITE: return GFX_DOOR_WHITE;
2836 case EL_DOOR_WHITE_GRAY: return GFX_DOOR_WHITE_GRAY;
2837 case EL_KEY_WHITE: return GFX_KEY_WHITE;
2838 case EL_SHIELD_NORMAL: return GFX_SHIELD_PASSIVE;
2839 case EL_SHIELD_DEADLY: return GFX_SHIELD_ACTIVE;
2840 case EL_EXTRA_TIME: return GFX_EXTRA_TIME;
2841 case EL_SWITCHGATE_OPEN: return GFX_SWITCHGATE_OPEN;
2842 case EL_SWITCHGATE_CLOSED: return GFX_SWITCHGATE_CLOSED;
2843 case EL_SWITCHGATE_SWITCH_UP: return GFX_SWITCHGATE_SWITCH_1;
2844 case EL_SWITCHGATE_SWITCH_DOWN: return GFX_SWITCHGATE_SWITCH_2;
2845 case EL_CONVEYOR_BELT1_LEFT: return GFX_BELT1_LEFT;
2846 case EL_CONVEYOR_BELT1_MIDDLE: return GFX_BELT1_MIDDLE;
2847 case EL_CONVEYOR_BELT1_RIGHT: return GFX_BELT1_RIGHT;
2848 case EL_CONVEYOR_BELT1_LEFT_ACTIVE: return GFX_BELT1_LEFT;
2849 case EL_CONVEYOR_BELT1_MIDDLE_ACTIVE:return GFX_BELT1_MIDDLE;
2850 case EL_CONVEYOR_BELT1_RIGHT_ACTIVE:return GFX_BELT1_RIGHT;
2851 case EL_CONVEYOR_BELT1_SWITCH_LEFT: return GFX_BELT1_SWITCH_LEFT;
2852 case EL_CONVEYOR_BELT1_SWITCH_MIDDLE:return GFX_BELT1_SWITCH_MIDDLE;
2853 case EL_CONVEYOR_BELT1_SWITCH_RIGHT:return GFX_BELT1_SWITCH_RIGHT;
2854 case EL_CONVEYOR_BELT2_LEFT: return GFX_BELT2_LEFT;
2855 case EL_CONVEYOR_BELT2_MIDDLE: return GFX_BELT2_MIDDLE;
2856 case EL_CONVEYOR_BELT2_RIGHT: return GFX_BELT2_RIGHT;
2857 case EL_CONVEYOR_BELT2_LEFT_ACTIVE: return GFX_BELT2_LEFT;
2858 case EL_CONVEYOR_BELT2_MIDDLE_ACTIVE:return GFX_BELT2_MIDDLE;
2859 case EL_CONVEYOR_BELT2_RIGHT_ACTIVE:return GFX_BELT2_RIGHT;
2860 case EL_CONVEYOR_BELT2_SWITCH_LEFT: return GFX_BELT2_SWITCH_LEFT;
2861 case EL_CONVEYOR_BELT2_SWITCH_MIDDLE:return GFX_BELT2_SWITCH_MIDDLE;
2862 case EL_CONVEYOR_BELT2_SWITCH_RIGHT:return GFX_BELT2_SWITCH_RIGHT;
2863 case EL_CONVEYOR_BELT3_LEFT: return GFX_BELT3_LEFT;
2864 case EL_CONVEYOR_BELT3_MIDDLE: return GFX_BELT3_MIDDLE;
2865 case EL_CONVEYOR_BELT3_RIGHT: return GFX_BELT3_RIGHT;
2866 case EL_CONVEYOR_BELT3_LEFT_ACTIVE: return GFX_BELT3_LEFT;
2867 case EL_CONVEYOR_BELT3_MIDDLE_ACTIVE:return GFX_BELT3_MIDDLE;
2868 case EL_CONVEYOR_BELT3_RIGHT_ACTIVE:return GFX_BELT3_RIGHT;
2869 case EL_CONVEYOR_BELT3_SWITCH_LEFT: return GFX_BELT3_SWITCH_LEFT;
2870 case EL_CONVEYOR_BELT3_SWITCH_MIDDLE:return GFX_BELT3_SWITCH_MIDDLE;
2871 case EL_CONVEYOR_BELT3_SWITCH_RIGHT:return GFX_BELT3_SWITCH_RIGHT;
2872 case EL_CONVEYOR_BELT4_LEFT: return GFX_BELT4_LEFT;
2873 case EL_CONVEYOR_BELT4_MIDDLE: return GFX_BELT4_MIDDLE;
2874 case EL_CONVEYOR_BELT4_RIGHT: return GFX_BELT4_RIGHT;
2875 case EL_CONVEYOR_BELT4_LEFT_ACTIVE: return GFX_BELT4_LEFT;
2876 case EL_CONVEYOR_BELT4_MIDDLE_ACTIVE:return GFX_BELT4_MIDDLE;
2877 case EL_CONVEYOR_BELT4_RIGHT_ACTIVE:return GFX_BELT4_RIGHT;
2878 case EL_CONVEYOR_BELT4_SWITCH_LEFT: return GFX_BELT4_SWITCH_LEFT;
2879 case EL_CONVEYOR_BELT4_SWITCH_MIDDLE:return GFX_BELT4_SWITCH_MIDDLE;
2880 case EL_CONVEYOR_BELT4_SWITCH_RIGHT:return GFX_BELT4_SWITCH_RIGHT;
2881 case EL_LANDMINE: return GFX_LANDMINE;
2882 case EL_ENVELOPE: return GFX_ENVELOPE;
2883 case EL_LIGHT_SWITCH: return GFX_LIGHT_SWITCH_OFF;
2884 case EL_LIGHT_SWITCH_ACTIVE: return GFX_LIGHT_SWITCH_ON;
2885 case EL_SIGN_EXCLAMATION: return GFX_SIGN_EXCLAMATION;
2886 case EL_SIGN_RADIOACTIVITY: return GFX_SIGN_RADIOACTIVITY;
2887 case EL_SIGN_STOP: return GFX_SIGN_STOP;
2888 case EL_SIGN_WHEELCHAIR: return GFX_SIGN_WHEELCHAIR;
2889 case EL_SIGN_PARKING: return GFX_SIGN_PARKING;
2890 case EL_SIGN_ONEWAY: return GFX_SIGN_ONEWAY;
2891 case EL_SIGN_HEART: return GFX_SIGN_HEART;
2892 case EL_SIGN_TRIANGLE: return GFX_SIGN_TRIANGLE;
2893 case EL_SIGN_ROUND: return GFX_SIGN_ROUND;
2894 case EL_SIGN_EXIT: return GFX_SIGN_EXIT;
2895 case EL_SIGN_YINYANG: return GFX_SIGN_YINYANG;
2896 case EL_SIGN_OTHER: return GFX_SIGN_OTHER;
2897 case EL_MOLE_LEFT: return GFX_MOLE_LEFT;
2898 case EL_MOLE_RIGHT: return GFX_MOLE_RIGHT;
2899 case EL_MOLE_UP: return GFX_MOLE_UP;
2900 case EL_MOLE_DOWN: return GFX_MOLE_DOWN;
2901 case EL_STEELWALL_SLANTED: return GFX_STEEL_SLANTED;
2902 case EL_INVISIBLE_SAND: return GFX_SAND_INVISIBLE;
2903 case EL_INVISIBLE_SAND_ACTIVE: return GFX_SAND_INVISIBLE_ON;
2904 case EL_DX_UNKNOWN_15: return GFX_DX_UNKNOWN_15;
2905 case EL_DX_UNKNOWN_42: return GFX_DX_UNKNOWN_42;
2906 case EL_TIMEGATE_OPEN: return GFX_TIMEGATE_OPEN;
2907 case EL_TIMEGATE_CLOSED: return GFX_TIMEGATE_CLOSED;
2908 case EL_TIMEGATE_SWITCH_ACTIVE: return GFX_TIMEGATE_SWITCH;
2909 case EL_TIMEGATE_SWITCH: return GFX_TIMEGATE_SWITCH;
2910 case EL_BALLOON: return GFX_BALLOON;
2911 case EL_BALLOON_SEND_LEFT: return GFX_BALLOON_SEND_LEFT;
2912 case EL_BALLOON_SEND_RIGHT: return GFX_BALLOON_SEND_RIGHT;
2913 case EL_BALLOON_SEND_UP: return GFX_BALLOON_SEND_UP;
2914 case EL_BALLOON_SEND_DOWN: return GFX_BALLOON_SEND_DOWN;
2915 case EL_BALLOON_SEND_ANY_DIRECTION: return GFX_BALLOON_SEND_ANY;
2916 case EL_EMC_STEELWALL1: return GFX_EMC_STEEL_WALL_1;
2917 case EL_EMC_STEELWALL2: return GFX_EMC_STEEL_WALL_2;
2918 case EL_EMC_STEELWALL3: return GFX_EMC_STEEL_WALL_3;
2919 case EL_EMC_STEELWALL4: return GFX_EMC_STEEL_WALL_4;
2920 case EL_EMC_WALL_PILLAR_UPPER: return GFX_EMC_WALL_1;
2921 case EL_EMC_WALL_PILLAR_MIDDLE: return GFX_EMC_WALL_2;
2922 case EL_EMC_WALL_PILLAR_LOWER: return GFX_EMC_WALL_3;
2923 case EL_EMC_WALL4: return GFX_EMC_WALL_4;
2924 case EL_EMC_WALL5: return GFX_EMC_WALL_5;
2925 case EL_EMC_WALL6: return GFX_EMC_WALL_6;
2926 case EL_EMC_WALL7: return GFX_EMC_WALL_7;
2927 case EL_EMC_WALL8: return GFX_EMC_WALL_8;
2928 case EL_TUBE_ALL: return GFX_TUBE_CROSS;
2929 case EL_TUBE_VERTICAL: return GFX_TUBE_VERTICAL;
2930 case EL_TUBE_HORIZONTAL: return GFX_TUBE_HORIZONTAL;
2931 case EL_TUBE_VERTICAL_LEFT: return GFX_TUBE_VERT_LEFT;
2932 case EL_TUBE_VERTICAL_RIGHT: return GFX_TUBE_VERT_RIGHT;
2933 case EL_TUBE_HORIZONTAL_UP: return GFX_TUBE_HORIZ_UP;
2934 case EL_TUBE_HORIZONTAL_DOWN: return GFX_TUBE_HORIZ_DOWN;
2935 case EL_TUBE_LEFT_UP: return GFX_TUBE_LEFT_UP;
2936 case EL_TUBE_LEFT_DOWN: return GFX_TUBE_LEFT_DOWN;
2937 case EL_TUBE_RIGHT_UP: return GFX_TUBE_RIGHT_UP;
2938 case EL_TUBE_RIGHT_DOWN: return GFX_TUBE_RIGHT_DOWN;
2939 case EL_SPRING: return GFX_SPRING;
2940 case EL_TRAP: return GFX_TRAP_INACTIVE;
2941 case EL_TRAP_ACTIVE: return GFX_TRAP_ACTIVE;
2942 case EL_BD_WALL: return GFX_BD_WALL;
2943 case EL_BD_ROCK: return GFX_BD_ROCK;
2944 case EL_DX_SUPABOMB: return GFX_DX_SUPABOMB;
2945 case EL_SP_MURPHY_CLONE: return GFX_SP_MURPHY_CLONE;
2949 if (IS_CHAR(element))
2950 return GFX_CHAR_START + (element - EL_CHAR_START);
2951 else if (element >= EL_SP_START && element <= EL_SP_END)
2953 int nr_element = element - EL_SP_START;
2954 int gfx_per_line = 8;
2956 (nr_element / gfx_per_line) * SP_PER_LINE +
2957 (nr_element % gfx_per_line);
2959 return GFX_START_ROCKSSP + nr_graphic;
2967 int el2gfx(int element)
2970 int graphic_OLD = el2gfx_OLD(element);
2975 int graphic_NEW = element_info[element].graphic[GFX_ACTION_DEFAULT];
2978 int graphic_OLD = el2gfx_OLD(element);
2980 if (element >= MAX_NUM_ELEMENTS)
2982 Error(ERR_WARN, "el2gfx: element == %d >= MAX_NUM_ELEMENTS", element);
2985 if (graphic_NEW != graphic_OLD)
2987 Error(ERR_WARN, "el2gfx: graphic_NEW (%d) != graphic_OLD (%d)",
2988 graphic_NEW, graphic_OLD);
2996 int el2img(int element)
2998 int graphic = element_info[element].graphic[GFX_ACTION_DEFAULT];
3002 Error(ERR_WARN, "element %d -> graphic %d -- probably crashing now...",
3009 int el_dir2img(int element, int direction)
3011 return el_dir_act2img(element, direction, GFX_ACTION_DEFAULT);
3014 int el_dir_act2img(int element, int direction, int action)
3019 printf("el_dir_act2img: THIS SHOULD NEVER HAPPEN: element == %d\n",
3027 printf("el_dir_act2img: THIS SHOULD NEVER HAPPEN: action == %d\n",
3034 action = graphics_action_mapping[action];
3035 direction = MV_DIR_BIT(direction);
3037 return element_info[element].direction_graphic[action][direction];