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);
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;
367 ClearRectangle(backbuffer, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
369 if (setup.soft_scrolling && game_status == PLAYING)
371 ClearRectangle(fieldbuffer, 0, 0, FXSIZE, FYSIZE);
372 SetDrawtoField(DRAW_BUFFERED);
375 SetDrawtoField(DRAW_BACKBUFFER);
377 if (setup.direct_draw && game_status == PLAYING)
379 ClearRectangle(window, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
380 SetDrawtoField(DRAW_DIRECT);
383 redraw_mask |= REDRAW_FIELD;
386 static int getGraphicAnimationPhase(int frames, int delay, int mode)
390 if (mode & ANIM_PINGPONG)
392 int max_anim_frames = 2 * frames - 2;
394 phase = (FrameCounter % (delay * max_anim_frames)) / delay;
395 phase = (phase < frames ? phase : max_anim_frames - phase);
398 phase = (FrameCounter % (delay * frames)) / delay;
400 if (mode & ANIM_REVERSE)
406 inline int getGraphicAnimationFrame(int graphic, int sync_frame)
408 /* animation synchronized with global frame counter, not move position */
409 if (new_graphic_info[graphic].anim_global_sync || sync_frame < 0)
410 sync_frame = FrameCounter;
412 return getAnimationFrame(new_graphic_info[graphic].anim_frames,
413 new_graphic_info[graphic].anim_delay,
414 new_graphic_info[graphic].anim_mode,
415 new_graphic_info[graphic].anim_start_frame,
419 void MarkTileDirty(int x, int y)
421 int xx = redraw_x1 + x;
422 int yy = redraw_y1 + y;
427 redraw[xx][yy] = TRUE;
428 redraw_mask |= REDRAW_TILES;
431 void SetBorderElement()
435 BorderElement = EL_EMPTY;
437 for(y=0; y<lev_fieldy && BorderElement == EL_EMPTY; y++)
439 for(x=0; x<lev_fieldx; x++)
441 if (!IS_MASSIVE(Feld[x][y]))
442 BorderElement = EL_STEELWALL;
444 if (y != 0 && y != lev_fieldy - 1 && x != lev_fieldx - 1)
450 void DrawAllPlayers()
454 for(i=0; i<MAX_PLAYERS; i++)
455 if (stored_player[i].active)
456 DrawPlayer(&stored_player[i]);
459 void DrawPlayerField(int x, int y)
461 if (!IS_PLAYER(x, y))
464 DrawPlayer(PLAYERINFO(x, y));
467 void DrawPlayer(struct PlayerInfo *player)
469 int jx = player->jx, jy = player->jy;
470 int last_jx = player->last_jx, last_jy = player->last_jy;
471 int next_jx = jx + (jx - last_jx), next_jy = jy + (jy - last_jy);
472 int sx = SCREENX(jx), sy = SCREENY(jy);
473 int sxx = 0, syy = 0;
474 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
477 boolean player_is_moving = (last_jx != jx || last_jy != jy ? TRUE : FALSE);
479 if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
483 if (!IN_LEV_FIELD(jx,jy))
485 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
486 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
487 printf("DrawPlayerField(): This should never happen!\n");
492 if (element == EL_EXPLOSION)
495 /* draw things in the field the player is leaving, if needed */
497 if (player_is_moving)
499 if (Store[last_jx][last_jy] && IS_DRAWABLE(last_element))
501 DrawLevelElement(last_jx, last_jy, Store[last_jx][last_jy]);
503 if (last_element == EL_DYNAMITE_ACTIVE)
504 DrawDynamite(last_jx, last_jy);
506 DrawLevelFieldThruMask(last_jx, last_jy);
508 else if (last_element == EL_DYNAMITE_ACTIVE)
509 DrawDynamite(last_jx, last_jy);
511 DrawLevelField(last_jx, last_jy);
513 if (player->Pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
517 if (Feld[next_jx][next_jy] == EL_SOKOBAN_FIELD_FULL)
518 DrawLevelElement(next_jx, next_jy, EL_SOKOBAN_FIELD_EMPTY);
520 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
523 DrawLevelField(next_jx, next_jy);
527 if (!IN_SCR_FIELD(sx, sy))
530 if (setup.direct_draw)
531 SetDrawtoField(DRAW_BUFFERED);
533 /* draw things behind the player, if needed */
536 DrawLevelElement(jx, jy, Store[jx][jy]);
537 else if (!IS_ACTIVE_BOMB(element))
538 DrawLevelField(jx, jy);
540 DrawLevelElement(jx, jy, EL_EMPTY);
542 /* draw player himself */
544 if (game.emulation == EMU_SUPAPLEX)
546 static int last_dir = MV_LEFT;
547 int action = (player->programmed_action ? player->programmed_action :
549 boolean action_moving =
551 ((action & (MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN)) &&
552 !(action & ~(MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN))));
554 graphic = IMG_SP_MURPHY;
558 if (player->MovDir == MV_LEFT)
559 graphic = IMG_SP_MURPHY_LEFT_PUSHING;
560 else if (player->MovDir == MV_RIGHT)
561 graphic = IMG_SP_MURPHY_RIGHT_PUSHING;
562 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
563 graphic = IMG_SP_MURPHY_LEFT_PUSHING;
564 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
565 graphic = IMG_SP_MURPHY_RIGHT_PUSHING;
567 else if (player->snapped)
569 if (player->MovDir == MV_LEFT)
570 graphic = IMG_SP_MURPHY_LEFT_SNAPPING;
571 else if (player->MovDir == MV_RIGHT)
572 graphic = IMG_SP_MURPHY_RIGHT_SNAPPING;
573 else if (player->MovDir == MV_UP)
574 graphic = IMG_SP_MURPHY_UP_SNAPPING;
575 else if (player->MovDir == MV_DOWN)
576 graphic = IMG_SP_MURPHY_DOWN_SNAPPING;
578 else if (action_moving)
580 if (player->MovDir == MV_LEFT)
581 graphic = IMG_SP_MURPHY_LEFT_MOVING;
582 else if (player->MovDir == MV_RIGHT)
583 graphic = IMG_SP_MURPHY_RIGHT_MOVING;
584 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
585 graphic = IMG_SP_MURPHY_LEFT_MOVING;
586 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
587 graphic = IMG_SP_MURPHY_RIGHT_MOVING;
589 graphic = IMG_SP_MURPHY_LEFT_MOVING;
591 frame = getGraphicAnimationFrame(graphic, -1);
594 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
595 last_dir = player->MovDir;
599 if (player->MovDir == MV_LEFT)
600 graphic = (player->Pushing ? IMG_PLAYER1_LEFT_PUSHING :
601 player->is_moving ? IMG_PLAYER1_LEFT_MOVING :
603 else if (player->MovDir == MV_RIGHT)
604 graphic = (player->Pushing ? IMG_PLAYER1_RIGHT_PUSHING :
605 player->is_moving ? IMG_PLAYER1_RIGHT_MOVING :
607 else if (player->MovDir == MV_UP)
608 graphic = (player->Pushing ? IMG_PLAYER1_UP_PUSHING :
609 player->is_moving ? IMG_PLAYER1_UP_MOVING :
611 else /* MV_DOWN || MV_NO_MOVING */
612 graphic = (player->Pushing ? IMG_PLAYER1_DOWN_PUSHING :
613 player->is_moving ? IMG_PLAYER1_DOWN_MOVING :
616 graphic = PLAYER_NR_GFX(graphic, player->index_nr);
619 frame = player->Frame;
621 frame = getGraphicAnimationFrame(graphic, player->Frame);
627 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
628 sxx = player->GfxPos;
630 syy = player->GfxPos;
633 if (!setup.soft_scrolling && ScreenMovPos)
638 printf("-> %d\n", player->Frame);
641 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
643 if (SHIELD_ON(player))
645 int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
646 IMG_SHIELD_NORMAL_ACTIVE);
647 int frame = getGraphicAnimationFrame(graphic, -1);
649 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
653 if (player->Pushing && player->GfxPos)
655 if (player->Pushing && player_is_moving)
658 int px = SCREENX(next_jx), py = SCREENY(next_jy);
660 if (element == EL_SOKOBAN_FIELD_EMPTY ||
661 Feld[next_jx][next_jy] == EL_SOKOBAN_FIELD_FULL)
662 DrawGraphicShiftedThruMask(px, py, sxx, syy, GFX_SOKOBAN_OBJEKT, 0,
666 int element = Feld[next_jx][next_jy];
667 int graphic = el2img(element);
672 if ((element == EL_ROCK ||
673 element == EL_BD_ROCK ||
674 element == EL_SP_ZONK) && sxx)
676 graphic = el_dir_act2img(element, player->MovDir, GFX_ACTION_MOVING);
678 frame = getGraphicAnimationFrame(graphic, player->GfxPos);
680 frame = getGraphicAnimationFrame(graphic, player->Frame);
684 printf("-> %d [%d]\n", player->Frame, player->GfxPos);
689 if (player->MovDir == MV_LEFT)
694 frame = (player->GfxPos / (TILEX / 4));
696 if (player->MovDir == MV_RIGHT)
697 frame = (frame + 4) % 4;
701 DrawGraphicShifted(px, py, sxx, syy, graphic, frame,
702 NO_CUTTING, NO_MASKING);
706 /* draw things in front of player (active dynamite or dynabombs) */
708 if (IS_ACTIVE_BOMB(element))
710 graphic = el2img(element);
713 if (element == EL_DYNAMITE_ACTIVE)
715 if ((frame = (96 - MovDelay[jx][jy]) / 12) > 6)
720 if ((frame = ((96 - MovDelay[jx][jy]) / 6) % 8) > 3)
724 frame = getGraphicAnimationFrame(graphic, 96 - MovDelay[jx][jy]);
727 if (game.emulation == EMU_SUPAPLEX)
728 DrawGraphic(sx, sy, GFX_SP_DISK_RED, 0);
730 DrawGraphicThruMask(sx, sy, graphic, frame);
733 if (player_is_moving && last_element == EL_EXPLOSION)
735 int stored = Store[last_jx][last_jy];
736 int graphic = (game.emulation != EMU_SUPAPLEX ? IMG_EXPLOSION :
737 stored == EL_SP_INFOTRON ? IMG_SP_EXPLOSION_INFOTRON :
739 int delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2);
740 int phase = Frame[last_jx][last_jy] - 1;
741 int frame = getGraphicAnimationFrame(graphic, phase - delay);
744 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy), graphic, frame);
747 /* draw elements that stay over the player */
748 /* handle the field the player is leaving ... */
749 if (player_is_moving && IS_OVER_PLAYER(last_element))
750 DrawLevelField(last_jx, last_jy);
752 /* ... and the field the player is entering */
753 if (IS_OVER_PLAYER(element))
754 DrawLevelField(jx, jy);
756 if (setup.direct_draw)
758 int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
759 int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
760 int x_size = TILEX * (1 + ABS(jx - last_jx));
761 int y_size = TILEY * (1 + ABS(jy - last_jy));
763 BlitBitmap(drawto_field, window,
764 dest_x, dest_y, x_size, y_size, dest_x, dest_y);
765 SetDrawtoField(DRAW_DIRECT);
768 MarkTileDirty(sx,sy);
771 void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
772 int graphic, int mask_mode)
774 int frame = getGraphicAnimationFrame(graphic, -1);
776 if (mask_mode == USE_MASKING)
777 DrawGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
779 DrawGraphicExt(dst_bitmap, x, y, graphic, frame);
782 void DrawGraphicAnimation(int x, int y, int graphic)
784 if (!IN_SCR_FIELD(x, y) ||
785 (FrameCounter % new_graphic_info[graphic].anim_delay) != 0)
788 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
789 graphic, NO_MASKING);
794 void getOldGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
796 if (graphic >= 0 && graphic_info[graphic].bitmap != NULL)
798 *bitmap = graphic_info[graphic].bitmap;
799 *x = graphic_info[graphic].src_x;
800 *y = graphic_info[graphic].src_y;
802 else if (graphic >= GFX_START_ROCKSELEMENTS &&
803 graphic <= GFX_END_ROCKSELEMENTS)
805 graphic -= GFX_START_ROCKSELEMENTS;
806 *bitmap = new_graphic_info[IMG_OLD_PIX_ELEMENTS].bitmap;
807 *x = (graphic % GFX_PER_LINE) * TILEX;
808 *y = (graphic / GFX_PER_LINE) * TILEY;
810 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
812 graphic -= GFX_START_ROCKSHEROES;
813 *bitmap = new_graphic_info[IMG_OLD_PIX_HEROES].bitmap;
814 *x = (graphic % HEROES_PER_LINE) * TILEX;
815 *y = (graphic / HEROES_PER_LINE) * TILEY;
817 else if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
819 graphic -= GFX_START_ROCKSSP;
820 *bitmap = new_graphic_info[IMG_OLD_PIX_SP].bitmap;
821 *x = (graphic % SP_PER_LINE) * TILEX;
822 *y = (graphic / SP_PER_LINE) * TILEY;
824 else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
826 graphic -= GFX_START_ROCKSDC;
827 *bitmap = new_graphic_info[IMG_OLD_PIX_DC].bitmap;
828 *x = (graphic % DC_PER_LINE) * TILEX;
829 *y = (graphic / DC_PER_LINE) * TILEY;
831 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
833 graphic -= GFX_START_ROCKSMORE;
834 *bitmap = new_graphic_info[IMG_OLD_PIX_MORE].bitmap;
835 *x = (graphic % MORE_PER_LINE) * TILEX;
836 *y = (graphic / MORE_PER_LINE) * TILEY;
838 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
840 graphic -= GFX_START_ROCKSFONT;
841 *bitmap = new_graphic_info[IMG_OLD_PIX_FONT_EM].bitmap;
842 *x = (graphic % FONT_CHARS_PER_LINE) * TILEX;
843 *y = (graphic / FONT_CHARS_PER_LINE) * TILEY;
847 *bitmap = new_graphic_info[IMG_OLD_PIX_SP].bitmap;
854 void getGraphicSource(int graphic, int frame, Bitmap **bitmap, int *x, int *y)
856 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
857 int offset_x = new_graphic_info[graphic].offset_x;
858 int offset_y = new_graphic_info[graphic].offset_y;
859 int src_x = new_graphic_info[graphic].src_x + frame * offset_x;
860 int src_y = new_graphic_info[graphic].src_y + frame * offset_y;
862 *bitmap = src_bitmap;
867 void DrawGraphic(int x, int y, int graphic, int frame)
870 if (!IN_SCR_FIELD(x, y))
872 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
873 printf("DrawGraphic(): This should never happen!\n");
878 DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic, frame);
883 void DrawOldGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic)
888 getOldGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
889 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
893 void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
900 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
902 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
903 int src_x = new_graphic_info[graphic].src_x;
904 int src_y = new_graphic_info[graphic].src_y;
905 int offset_x = new_graphic_info[graphic].offset_x;
906 int offset_y = new_graphic_info[graphic].offset_y;
908 src_x += frame * offset_x;
909 src_y += frame * offset_y;
912 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
915 void DrawGraphicThruMask(int x, int y, int graphic, int frame)
918 if (!IN_SCR_FIELD(x, y))
920 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
921 printf("DrawGraphicThruMask(): This should never happen!\n");
926 DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY, graphic,
931 void DrawGraphicThruMaskExt(DrawBuffer *d, int dest_x, int dest_y, int graphic,
939 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
940 drawing_gc = src_bitmap->stored_clip_gc;
942 GC drawing_gc = src_bitmap->stored_clip_gc;
943 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
944 int src_x = new_graphic_info[graphic].src_x;
945 int src_y = new_graphic_info[graphic].src_y;
946 int offset_x = new_graphic_info[graphic].offset_x;
947 int offset_y = new_graphic_info[graphic].offset_y;
949 src_x += frame * offset_x;
950 src_y += frame * offset_y;
954 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
955 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dest_x, dest_y);
958 void DrawMiniGraphic(int x, int y, int graphic)
960 DrawMiniGraphicExt(drawto, SX + x * MINI_TILEX,SY + y * MINI_TILEY, graphic);
961 MarkTileDirty(x / 2, y / 2);
964 void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
966 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
968 int mini_starty = src_bitmap->height * 2 / 3;
969 int src_x = mini_startx + new_graphic_info[graphic].src_x / 2;
970 int src_y = mini_starty + new_graphic_info[graphic].src_y / 2;
972 if (src_x + MINI_TILEX > src_bitmap->width ||
973 src_y + MINI_TILEY > src_bitmap->height)
975 /* graphic of desired size seems not to be contained in this image;
976 dirty workaround: get it from the middle of the normal sized image */
978 getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
979 src_x += (TILEX / 2 - MINI_TILEX / 2);
980 src_y += (TILEY / 2 - MINI_TILEY / 2);
983 *bitmap = src_bitmap;
988 void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
993 getMiniGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
994 BlitBitmap(src_bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
997 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic, int frame,
998 int cut_mode, int mask_mode)
1007 int width = TILEX, height = TILEY;
1013 DrawGraphic(x, y, graphic, frame);
1017 if (dx || dy) /* shifted graphic */
1019 if (x < BX1) /* object enters playfield from the left */
1026 else if (x > BX2) /* object enters playfield from the right */
1032 else if (x==BX1 && dx < 0) /* object leaves playfield to the left */
1038 else if (x==BX2 && dx > 0) /* object leaves playfield to the right */
1040 else if (dx) /* general horizontal movement */
1041 MarkTileDirty(x + SIGN(dx), y);
1043 if (y < BY1) /* object enters playfield from the top */
1045 if (cut_mode==CUT_BELOW) /* object completely above top border */
1053 else if (y > BY2) /* object enters playfield from the bottom */
1059 else if (y==BY1 && dy < 0) /* object leaves playfield to the top */
1065 else if (dy > 0 && cut_mode == CUT_ABOVE)
1067 if (y == BY2) /* object completely above bottom border */
1073 MarkTileDirty(x, y + 1);
1074 } /* object leaves playfield to the bottom */
1075 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1077 else if (dy) /* general vertical movement */
1078 MarkTileDirty(x, y + SIGN(dy));
1081 src_bitmap = new_graphic_info[graphic].bitmap;
1082 src_x = new_graphic_info[graphic].src_x;
1083 src_y = new_graphic_info[graphic].src_y;
1084 offset_x = new_graphic_info[graphic].offset_x;
1085 offset_y = new_graphic_info[graphic].offset_y;
1087 drawing_gc = src_bitmap->stored_clip_gc;
1089 src_x += frame * offset_x;
1090 src_y += frame * offset_y;
1095 dest_x = FX + x * TILEX + dx;
1096 dest_y = FY + y * TILEY + dy;
1099 if (!IN_SCR_FIELD(x,y))
1101 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1102 printf("DrawGraphicShifted(): This should never happen!\n");
1107 if (mask_mode == USE_MASKING)
1109 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1110 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
1114 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1120 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
1121 int frame, int cut_mode)
1123 DrawGraphicShifted(x,y, dx,dy, graphic, frame, cut_mode, USE_MASKING);
1127 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1128 int cut_mode, int mask_mode)
1130 int ux = LEVELX(x), uy = LEVELY(y);
1131 int graphic = el2gfx(element);
1132 int phase8 = ABS(MovPos[ux][uy]) / (TILEX / 8);
1133 int phase4 = phase8 / 2;
1134 int phase2 = phase8 / 4;
1135 int dir = MovDir[ux][uy];
1137 if (element == EL_PACMAN || element == EL_BUG || element == EL_SPACESHIP)
1139 graphic += 1 * !phase2;
1143 else if (dir == MV_LEFT)
1145 else if (dir == MV_DOWN)
1148 else if (element == EL_SP_SNIKSNAK)
1151 graphic = GFX_SP_SNIKSNAK_LEFT;
1152 else if (dir == MV_RIGHT)
1153 graphic = GFX_SP_SNIKSNAK_RIGHT;
1154 else if (dir == MV_UP)
1155 graphic = GFX_SP_SNIKSNAK_UP;
1157 graphic = GFX_SP_SNIKSNAK_DOWN;
1159 graphic += (phase8 < 4 ? phase8 : 7 - phase8);
1161 else if (element == EL_SP_ELECTRON)
1163 graphic = GFX2_SP_ELECTRON + getGraphicAnimationPhase(8, 2, ANIM_LOOP);
1165 else if (element == EL_MOLE || element == EL_PENGUIN ||
1166 element == EL_PIG || element == EL_DRAGON)
1169 graphic = (element == EL_MOLE ? GFX_MOLE_LEFT :
1170 element == EL_PENGUIN ? GFX_PINGUIN_LEFT :
1171 element == EL_PIG ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
1172 else if (dir == MV_RIGHT)
1173 graphic = (element == EL_MOLE ? GFX_MOLE_RIGHT :
1174 element == EL_PENGUIN ? GFX_PINGUIN_RIGHT :
1175 element == EL_PIG ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
1176 else if (dir == MV_UP)
1177 graphic = (element == EL_MOLE ? GFX_MOLE_UP :
1178 element == EL_PENGUIN ? GFX_PINGUIN_UP :
1179 element == EL_PIG ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
1181 graphic = (element == EL_MOLE ? GFX_MOLE_DOWN :
1182 element == EL_PENGUIN ? GFX_PINGUIN_DOWN :
1183 element == EL_PIG ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
1187 else if (element == EL_SATELLITE)
1189 graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_LOOP);
1191 else if (element == EL_ACID)
1193 graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_LOOP);
1195 else if (element == EL_BD_BUTTERFLY || element == EL_BD_FIREFLY)
1199 else if (element == EL_BALLOON)
1203 else if ((element == EL_ROCK ||
1204 element == EL_SP_ZONK ||
1205 element == EL_BD_ROCK ||
1206 element == EL_SP_INFOTRON ||
1210 if (uy >= lev_fieldy-1 || !IS_BELT(Feld[ux][uy+1]))
1212 if (element == EL_ROCK ||
1213 element == EL_SP_ZONK ||
1214 element == EL_BD_ROCK)
1217 graphic += (4 - phase4) % 4;
1218 else if (dir == MV_RIGHT)
1221 graphic += phase2 * 2;
1223 else if (element != EL_SP_INFOTRON)
1227 else if (element == EL_MAGIC_WALL_ACTIVE ||
1228 element == EL_MAGIC_WALL_EMPTYING ||
1229 element == EL_BD_MAGIC_WALL_ACTIVE ||
1230 element == EL_BD_MAGIC_WALL_EMPTYING ||
1231 element == EL_MAGIC_WALL_FULL ||
1232 element == EL_BD_MAGIC_WALL_FULL)
1234 graphic += 3 + getGraphicAnimationPhase(4, 4, ANIM_REVERSE);
1236 else if (IS_AMOEBOID(element) || element == EL_AMOEBA_DRIPPING)
1238 graphic = (element == EL_AMOEBA_DEAD ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
1239 graphic += (x + 2 * y + 4) % 4;
1241 else if (element == EL_WALL_GROWING)
1243 boolean links_massiv = FALSE, rechts_massiv = FALSE;
1245 if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
1246 links_massiv = TRUE;
1247 if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
1248 rechts_massiv = TRUE;
1250 if (links_massiv && rechts_massiv)
1251 graphic = GFX_MAUERWERK;
1252 else if (links_massiv)
1253 graphic = GFX_MAUER_R;
1254 else if (rechts_massiv)
1255 graphic = GFX_MAUER_L;
1258 else if ((element == EL_INVISIBLE_STEELWALL ||
1259 element == EL_INVISIBLE_WALL ||
1260 element == EL_INVISIBLE_SAND) && game.light_time_left)
1262 graphic = (element == EL_INVISIBLE_STEELWALL ? GFX_INVISIBLE_STEEL_ON :
1263 element == EL_INVISIBLE_WALL ? GFX_UNSICHTBAR_ON :
1264 GFX_SAND_INVISIBLE_ON);
1269 DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
1270 else if (mask_mode == USE_MASKING)
1271 DrawGraphicThruMask(x, y, graphic);
1273 DrawGraphic(x, y, graphic);
1277 inline static int getFramePosition(int x, int y)
1279 int frame_pos = -1; /* default: global synchronization */
1281 int element = Feld[x][y];
1283 if (element == EL_QUICKSAND_FULL ||
1284 element == EL_MAGIC_WALL_FULL ||
1285 element == EL_BD_MAGIC_WALL_FULL)
1287 else if (IS_MOVING(x, y) || CAN_MOVE(element) || CAN_FALL(element))
1288 frame_pos = ABS(MovPos[x][y]) / (TILEX / 8);
1290 frame_pos = ABS(MovPos[x][y]) / (TILEX / 8);
1296 inline static int getGfxAction(int x, int y)
1298 int gfx_action = GFX_ACTION_DEFAULT;
1301 if (GfxAction[x][y] != GFX_ACTION_DEFAULT)
1302 gfx_action = GfxAction[x][y];
1303 else if (IS_MOVING(x, y))
1304 gfx_action = GFX_ACTION_MOVING;
1306 gfx_action = GfxAction[x][y];
1311 printf("getGfxAction: THIS SHOULD NEVER HAPPEN: GfxAction[%d][%d] == %d\n",
1318 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1319 int cut_mode, int mask_mode)
1321 int ux = LEVELX(x), uy = LEVELY(y);
1325 if (IN_LEV_FIELD(ux, uy))
1327 int move_dir = MovDir[ux][uy];
1328 int move_pos = getFramePosition(ux, uy);
1329 int gfx_action = getGfxAction(ux, uy);
1331 graphic = el_dir_act2img(element, move_dir, gfx_action);
1332 frame = getGraphicAnimationFrame(graphic, move_pos);
1336 graphic = el2img(element);
1337 frame = getGraphicAnimationFrame(graphic, 0);
1340 if (element == EL_WALL_GROWING)
1342 boolean left_stopped = FALSE, right_stopped = FALSE;
1344 if (!IN_LEV_FIELD(ux - 1, uy) || IS_MAUER(Feld[ux - 1][uy]))
1345 left_stopped = TRUE;
1346 if (!IN_LEV_FIELD(ux + 1, uy) || IS_MAUER(Feld[ux + 1][uy]))
1347 right_stopped = TRUE;
1349 if (left_stopped && right_stopped)
1351 else if (left_stopped)
1353 graphic = IMG_WALL_GROWING_ACTIVE_RIGHT;
1354 frame = new_graphic_info[graphic].anim_frames - 1;
1356 else if (right_stopped)
1358 graphic = IMG_WALL_GROWING_ACTIVE_LEFT;
1359 frame = new_graphic_info[graphic].anim_frames - 1;
1362 else if (IS_AMOEBOID(element) || element == EL_AMOEBA_DRIPPING)
1364 graphic = (element == EL_BD_AMOEBA ? IMG_BD_AMOEBA_PART1 :
1365 element == EL_AMOEBA_WET ? IMG_AMOEBA_WET_PART1 :
1366 element == EL_AMOEBA_DRY ? IMG_AMOEBA_DRY_PART1 :
1367 element == EL_AMOEBA_FULL ? IMG_AMOEBA_FULL_PART1 :
1368 IMG_AMOEBA_DEAD_PART1);
1370 graphic += (x + 2 * y + 4) % 4;
1374 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
1375 else if (mask_mode == USE_MASKING)
1376 DrawGraphicThruMask(x, y, graphic, frame);
1378 DrawGraphic(x, y, graphic, frame);
1381 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1382 int cut_mode, int mask_mode)
1384 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1385 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1386 cut_mode, mask_mode);
1389 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1392 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1395 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1398 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1402 void DrawOldScreenElementThruMask(int x, int y, int element)
1404 DrawOldScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1407 void DrawScreenElementThruMask(int x, int y, int element)
1409 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1413 void DrawLevelElementThruMask(int x, int y, int element)
1415 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1418 void DrawLevelFieldThruMask(int x, int y)
1420 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1423 void DrawCrumbledSand(int x, int y)
1427 int i, width, height, cx,cy;
1428 int ux = LEVELX(x), uy = LEVELY(y);
1429 int element, graphic;
1431 static int xy[4][2] =
1439 if (!IN_LEV_FIELD(ux, uy))
1442 element = Feld[ux][uy];
1444 if (element == EL_SAND ||
1445 element == EL_LANDMINE ||
1446 element == EL_TRAP ||
1447 element == EL_TRAP_ACTIVE)
1449 if (!IN_SCR_FIELD(x, y))
1452 graphic = IMG_SAND_CRUMBLED;
1454 src_bitmap = new_graphic_info[graphic].bitmap;
1455 src_x = new_graphic_info[graphic].src_x;
1456 src_y = new_graphic_info[graphic].src_y;
1462 uxx = ux + xy[i][0];
1463 uyy = uy + xy[i][1];
1464 if (!IN_LEV_FIELD(uxx, uyy))
1465 element = EL_STEELWALL;
1467 element = Feld[uxx][uyy];
1469 if (element == EL_SAND ||
1470 element == EL_LANDMINE ||
1471 element == EL_TRAP ||
1472 element == EL_TRAP_ACTIVE)
1475 if (i == 1 || i == 2)
1479 cx = (i == 2 ? TILEX - snip : 0);
1487 cy = (i == 3 ? TILEY - snip : 0);
1490 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1491 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1494 MarkTileDirty(x, y);
1498 graphic = IMG_SAND_CRUMBLED;
1500 src_bitmap = new_graphic_info[graphic].bitmap;
1501 src_x = new_graphic_info[graphic].src_x;
1502 src_y = new_graphic_info[graphic].src_y;
1506 int xx, yy, uxx, uyy;
1510 uxx = ux + xy[i][0];
1511 uyy = uy + xy[i][1];
1513 if (!IN_LEV_FIELD(uxx, uyy) ||
1514 (Feld[uxx][uyy] != EL_SAND &&
1515 Feld[uxx][uyy] != EL_LANDMINE &&
1516 Feld[uxx][uyy] != EL_TRAP &&
1517 Feld[uxx][uyy] != EL_TRAP_ACTIVE) ||
1518 !IN_SCR_FIELD(xx, yy))
1521 if (i == 1 || i == 2)
1525 cx = (i == 1 ? TILEX - snip : 0);
1533 cy = (i==0 ? TILEY-snip : 0);
1536 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1537 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1539 MarkTileDirty(xx, yy);
1544 void DrawScreenElement(int x, int y, int element)
1546 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1547 DrawCrumbledSand(x, y);
1550 void DrawLevelElement(int x, int y, int element)
1552 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1553 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1556 void DrawScreenField(int x, int y)
1558 int ux = LEVELX(x), uy = LEVELY(y);
1559 int element, content;
1561 if (!IN_LEV_FIELD(ux, uy))
1563 if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
1566 element = BorderElement;
1568 DrawScreenElement(x, y, element);
1572 element = Feld[ux][uy];
1573 content = Store[ux][uy];
1575 if (IS_MOVING(ux, uy))
1577 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1578 boolean cut_mode = NO_CUTTING;
1580 if (element == EL_QUICKSAND_EMPTYING ||
1581 element == EL_MAGIC_WALL_EMPTYING ||
1582 element == EL_BD_MAGIC_WALL_EMPTYING ||
1583 element == EL_AMOEBA_DRIPPING)
1584 cut_mode = CUT_ABOVE;
1585 else if (element == EL_QUICKSAND_FILLING ||
1586 element == EL_MAGIC_WALL_FILLING ||
1587 element == EL_BD_MAGIC_WALL_FILLING)
1588 cut_mode = CUT_BELOW;
1590 if (cut_mode == CUT_ABOVE)
1591 DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1593 DrawScreenElement(x, y, EL_EMPTY);
1596 DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1597 else if (cut_mode == NO_CUTTING)
1598 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1600 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], content, cut_mode);
1602 if (content == EL_ACID)
1603 DrawLevelElementThruMask(ux, uy + 1, EL_ACID);
1605 else if (IS_BLOCKED(ux, uy))
1610 boolean cut_mode = NO_CUTTING;
1611 int element_old, content_old;
1613 Blocked2Moving(ux, uy, &oldx, &oldy);
1616 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1617 MovDir[oldx][oldy] == MV_RIGHT);
1619 element_old = Feld[oldx][oldy];
1620 content_old = Store[oldx][oldy];
1622 if (element_old == EL_QUICKSAND_EMPTYING ||
1623 element_old == EL_MAGIC_WALL_EMPTYING ||
1624 element_old == EL_BD_MAGIC_WALL_EMPTYING ||
1625 element_old == EL_AMOEBA_DRIPPING)
1626 cut_mode = CUT_ABOVE;
1628 DrawScreenElement(x, y, EL_EMPTY);
1631 DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
1633 else if (cut_mode == NO_CUTTING)
1634 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
1637 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
1640 else if (IS_DRAWABLE(element))
1641 DrawScreenElement(x, y, element);
1643 DrawScreenElement(x, y, EL_EMPTY);
1646 void DrawLevelField(int x, int y)
1648 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1649 DrawScreenField(SCREENX(x), SCREENY(y));
1650 else if (IS_MOVING(x, y))
1654 Moving2Blocked(x, y, &newx, &newy);
1655 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1656 DrawScreenField(SCREENX(newx), SCREENY(newy));
1658 else if (IS_BLOCKED(x, y))
1662 Blocked2Moving(x, y, &oldx, &oldy);
1663 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1664 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1668 void DrawMiniElement(int x, int y, int element)
1672 graphic = el2img(element);
1673 DrawMiniGraphic(x, y, graphic);
1676 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1678 int x = sx + scroll_x, y = sy + scroll_y;
1680 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1681 DrawMiniElement(sx, sy, EL_EMPTY);
1682 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1683 DrawMiniElement(sx, sy, Feld[x][y]);
1686 int steel_type, steel_position;
1689 { IMG_STEELWALL_TOPLEFT, IMG_INVISIBLE_STEELWALL_TOPLEFT },
1690 { IMG_STEELWALL_TOPRIGHT, IMG_INVISIBLE_STEELWALL_TOPRIGHT },
1691 { IMG_STEELWALL_BOTTOMLEFT, IMG_INVISIBLE_STEELWALL_BOTTOMLEFT },
1692 { IMG_STEELWALL_BOTTOMRIGHT, IMG_INVISIBLE_STEELWALL_BOTTOMRIGHT },
1693 { IMG_STEELWALL_VERTICAL, IMG_INVISIBLE_STEELWALL_VERTICAL },
1694 { IMG_STEELWALL_HORIZONTAL, IMG_INVISIBLE_STEELWALL_HORIZONTAL }
1697 steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
1698 steel_position = (x == -1 && y == -1 ? 0 :
1699 x == lev_fieldx && y == -1 ? 1 :
1700 x == -1 && y == lev_fieldy ? 2 :
1701 x == lev_fieldx && y == lev_fieldy ? 3 :
1702 x == -1 || x == lev_fieldx ? 4 :
1703 y == -1 || y == lev_fieldy ? 5 : -1);
1705 if (steel_position != -1)
1706 DrawMiniGraphic(sx, sy, border[steel_position][steel_type]);
1710 void getMicroGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1712 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
1713 int mini_startx = src_bitmap->width * 3 / 4;
1714 int mini_starty = src_bitmap->height * 2 / 3;
1715 int src_x = mini_startx + new_graphic_info[graphic].src_x / 8;
1716 int src_y = mini_starty + new_graphic_info[graphic].src_y / 8;
1718 if (src_x + MICRO_TILEX > src_bitmap->width ||
1719 src_y + MICRO_TILEY > src_bitmap->height)
1721 /* graphic of desired size seems not to be contained in this image;
1722 dirty workaround: get it from the middle of the normal sized image */
1724 getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
1725 src_x += (TILEX / 2 - MICRO_TILEX / 2);
1726 src_y += (TILEY / 2 - MICRO_TILEY / 2);
1729 *bitmap = src_bitmap;
1734 void DrawMicroElement(int xpos, int ypos, int element)
1740 if (element == EL_EMPTY)
1743 graphic = el2img(element);
1745 getMicroGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1746 BlitBitmap(src_bitmap, drawto, src_x, src_y, MICRO_TILEX, MICRO_TILEY,
1756 for(x=BX1; x<=BX2; x++)
1757 for(y=BY1; y<=BY2; y++)
1758 DrawScreenField(x, y);
1760 redraw_mask |= REDRAW_FIELD;
1763 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1767 for(x=0; x<size_x; x++)
1768 for(y=0; y<size_y; y++)
1769 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1771 redraw_mask |= REDRAW_FIELD;
1774 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1778 ClearRectangle(drawto, xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
1780 if (lev_fieldx < STD_LEV_FIELDX)
1781 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1782 if (lev_fieldy < STD_LEV_FIELDY)
1783 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1785 xpos += MICRO_TILEX;
1786 ypos += MICRO_TILEY;
1788 for(x=-1; x<=STD_LEV_FIELDX; x++)
1790 for(y=-1; y<=STD_LEV_FIELDY; y++)
1792 int lx = from_x + x, ly = from_y + y;
1794 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1795 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1797 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1)
1798 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1803 redraw_mask |= REDRAW_MICROLEVEL;
1806 #define MICROLABEL_EMPTY 0
1807 #define MICROLABEL_LEVEL_NAME 1
1808 #define MICROLABEL_CREATED_BY 2
1809 #define MICROLABEL_LEVEL_AUTHOR 3
1810 #define MICROLABEL_IMPORTED_FROM 4
1811 #define MICROLABEL_LEVEL_IMPORT_INFO 5
1813 #define MAX_MICROLABEL_SIZE (SXSIZE / FONT4_XSIZE)
1815 static void DrawMicroLevelLabelExt(int mode)
1817 char label_text[MAX_MICROLABEL_SIZE + 1];
1819 ClearRectangle(drawto, SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
1821 strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
1822 mode == MICROLABEL_CREATED_BY ? "created by" :
1823 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
1824 mode == MICROLABEL_IMPORTED_FROM ? "imported from" :
1825 mode == MICROLABEL_LEVEL_IMPORT_INFO ?
1826 leveldir_current->imported_from : ""),
1827 MAX_MICROLABEL_SIZE);
1828 label_text[MAX_MICROLABEL_SIZE] = '\0';
1830 if (strlen(label_text) > 0)
1832 int lxpos = SX + (SXSIZE - strlen(label_text) * FONT4_XSIZE) / 2;
1833 int lypos = MICROLABEL_YPOS;
1835 DrawText(lxpos, lypos, label_text, FS_SMALL, FC_SPECIAL2);
1838 redraw_mask |= REDRAW_MICROLEVEL;
1841 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1843 static unsigned long scroll_delay = 0;
1844 static unsigned long label_delay = 0;
1845 static int from_x, from_y, scroll_direction;
1846 static int label_state, label_counter;
1850 from_x = from_y = 0;
1851 scroll_direction = MV_RIGHT;
1855 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1856 DrawMicroLevelLabelExt(label_state);
1858 /* initialize delay counters */
1859 DelayReached(&scroll_delay, 0);
1860 DelayReached(&label_delay, 0);
1865 /* scroll micro level, if needed */
1866 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1867 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1869 switch (scroll_direction)
1875 scroll_direction = MV_UP;
1879 if (from_x < lev_fieldx - STD_LEV_FIELDX)
1882 scroll_direction = MV_DOWN;
1889 scroll_direction = MV_RIGHT;
1893 if (from_y < lev_fieldy - STD_LEV_FIELDY)
1896 scroll_direction = MV_LEFT;
1903 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1906 /* redraw micro level label, if needed */
1907 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1908 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1909 strcmp(level.author, leveldir_current->name) != 0 &&
1910 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1912 int max_label_counter = 23;
1914 if (leveldir_current->imported_from != NULL)
1915 max_label_counter += 14;
1917 label_counter = (label_counter + 1) % max_label_counter;
1918 label_state = (label_counter >= 0 && label_counter <= 7 ?
1919 MICROLABEL_LEVEL_NAME :
1920 label_counter >= 9 && label_counter <= 12 ?
1921 MICROLABEL_CREATED_BY :
1922 label_counter >= 14 && label_counter <= 21 ?
1923 MICROLABEL_LEVEL_AUTHOR :
1924 label_counter >= 23 && label_counter <= 26 ?
1925 MICROLABEL_IMPORTED_FROM :
1926 label_counter >= 28 && label_counter <= 35 ?
1927 MICROLABEL_LEVEL_IMPORT_INFO : MICROLABEL_EMPTY);
1928 DrawMicroLevelLabelExt(label_state);
1932 int REQ_in_range(int x, int y)
1934 if (y > DY+249 && y < DY+278)
1936 if (x > DX+1 && x < DX+48)
1938 else if (x > DX+51 && x < DX+98)
1944 #define MAX_REQUEST_LINES 13
1945 #define MAX_REQUEST_LINE_LEN 7
1947 boolean Request(char *text, unsigned int req_state)
1949 int mx, my, ty, result = -1;
1950 unsigned int old_door_state;
1952 #if defined(PLATFORM_UNIX)
1953 /* pause network game while waiting for request to answer */
1954 if (options.network &&
1955 game_status == PLAYING &&
1956 req_state & REQUEST_WAIT_FOR)
1957 SendToServer_PausePlaying();
1960 old_door_state = GetDoorState();
1964 CloseDoor(DOOR_CLOSE_1);
1966 /* save old door content */
1967 BlitBitmap(bitmap_db_door, bitmap_db_door,
1968 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
1969 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
1971 /* clear door drawing field */
1972 ClearRectangle(drawto, DX, DY, DXSIZE, DYSIZE);
1974 /* write text for request */
1975 for(ty=0; ty < MAX_REQUEST_LINES; ty++)
1977 char text_line[MAX_REQUEST_LINE_LEN + 1];
1983 for(tl=0,tx=0; tx < MAX_REQUEST_LINE_LEN; tl++,tx++)
1986 if (!tc || tc == ' ')
1997 strncpy(text_line, text, tl);
2000 DrawTextExt(drawto, DX + 50 - (tl * 14)/2, DY + 8 + ty * 16,
2001 text_line, FS_SMALL, FC_YELLOW);
2003 text += tl + (tc == ' ' ? 1 : 0);
2006 if (req_state & REQ_ASK)
2008 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
2009 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
2011 else if (req_state & REQ_CONFIRM)
2013 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
2015 else if (req_state & REQ_PLAYER)
2017 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
2018 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
2019 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
2020 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
2023 /* copy request gadgets to door backbuffer */
2024 BlitBitmap(drawto, bitmap_db_door,
2025 DX, DY, DXSIZE, DYSIZE,
2026 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2028 OpenDoor(DOOR_OPEN_1);
2034 if (!(req_state & REQUEST_WAIT_FOR))
2037 if (game_status != MAINMENU)
2040 button_status = MB_RELEASED;
2042 request_gadget_id = -1;
2054 case EVENT_BUTTONPRESS:
2055 case EVENT_BUTTONRELEASE:
2056 case EVENT_MOTIONNOTIFY:
2058 if (event.type == EVENT_MOTIONNOTIFY)
2060 if (!PointerInWindow(window))
2061 continue; /* window and pointer are on different screens */
2066 motion_status = TRUE;
2067 mx = ((MotionEvent *) &event)->x;
2068 my = ((MotionEvent *) &event)->y;
2072 motion_status = FALSE;
2073 mx = ((ButtonEvent *) &event)->x;
2074 my = ((ButtonEvent *) &event)->y;
2075 if (event.type == EVENT_BUTTONPRESS)
2076 button_status = ((ButtonEvent *) &event)->button;
2078 button_status = MB_RELEASED;
2081 /* this sets 'request_gadget_id' */
2082 HandleGadgets(mx, my, button_status);
2084 switch(request_gadget_id)
2086 case TOOL_CTRL_ID_YES:
2089 case TOOL_CTRL_ID_NO:
2092 case TOOL_CTRL_ID_CONFIRM:
2093 result = TRUE | FALSE;
2096 case TOOL_CTRL_ID_PLAYER_1:
2099 case TOOL_CTRL_ID_PLAYER_2:
2102 case TOOL_CTRL_ID_PLAYER_3:
2105 case TOOL_CTRL_ID_PLAYER_4:
2116 case EVENT_KEYPRESS:
2117 switch(GetEventKey((KeyEvent *)&event, TRUE))
2130 if (req_state & REQ_PLAYER)
2134 case EVENT_KEYRELEASE:
2135 ClearPlayerAction();
2139 HandleOtherEvents(&event);
2143 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2145 int joy = AnyJoystick();
2147 if (joy & JOY_BUTTON_1)
2149 else if (joy & JOY_BUTTON_2)
2155 /* don't eat all CPU time */
2159 if (game_status != MAINMENU)
2164 if (!(req_state & REQ_STAY_OPEN))
2166 CloseDoor(DOOR_CLOSE_1);
2168 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
2170 BlitBitmap(bitmap_db_door, bitmap_db_door,
2171 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
2172 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
2173 OpenDoor(DOOR_OPEN_1);
2179 #if defined(PLATFORM_UNIX)
2180 /* continue network game after request */
2181 if (options.network &&
2182 game_status == PLAYING &&
2183 req_state & REQUEST_WAIT_FOR)
2184 SendToServer_ContinuePlaying();
2190 unsigned int OpenDoor(unsigned int door_state)
2192 unsigned int new_door_state;
2194 if (door_state & DOOR_COPY_BACK)
2196 BlitBitmap(bitmap_db_door, bitmap_db_door,
2197 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
2198 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2199 door_state &= ~DOOR_COPY_BACK;
2202 new_door_state = MoveDoor(door_state);
2204 return(new_door_state);
2207 unsigned int CloseDoor(unsigned int door_state)
2209 unsigned int new_door_state;
2211 BlitBitmap(backbuffer, bitmap_db_door,
2212 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2213 BlitBitmap(backbuffer, bitmap_db_door,
2214 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2216 new_door_state = MoveDoor(door_state);
2218 return(new_door_state);
2221 unsigned int GetDoorState()
2223 return MoveDoor(DOOR_GET_STATE);
2226 unsigned int SetDoorState(unsigned int door_state)
2228 return MoveDoor(door_state | DOOR_SET_STATE);
2231 unsigned int MoveDoor(unsigned int door_state)
2233 static int door1 = DOOR_OPEN_1;
2234 static int door2 = DOOR_CLOSE_2;
2235 static unsigned long door_delay = 0;
2236 int x, start, stepsize = 2;
2237 unsigned long door_delay_value = stepsize * 5;
2239 if (door_state == DOOR_GET_STATE)
2240 return(door1 | door2);
2242 if (door_state & DOOR_SET_STATE)
2244 if (door_state & DOOR_ACTION_1)
2245 door1 = door_state & DOOR_ACTION_1;
2246 if (door_state & DOOR_ACTION_2)
2247 door2 = door_state & DOOR_ACTION_2;
2249 return(door1 | door2);
2252 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2253 door_state &= ~DOOR_OPEN_1;
2254 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2255 door_state &= ~DOOR_CLOSE_1;
2256 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2257 door_state &= ~DOOR_OPEN_2;
2258 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2259 door_state &= ~DOOR_CLOSE_2;
2261 if (setup.quick_doors)
2264 door_delay_value = 0;
2266 StopSound(SND_MENU_DOOR_OPENING);
2267 StopSound(SND_MENU_DOOR_CLOSING);
2270 if (global.autoplay_leveldir)
2272 door_state |= DOOR_NO_DELAY;
2273 door_state &= ~DOOR_CLOSE_ALL;
2276 if (door_state & DOOR_ACTION)
2278 if (!(door_state & DOOR_NO_DELAY))
2280 /* opening door sound has priority over simultaneously closing door */
2281 if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
2282 PlaySoundStereo(SND_MENU_DOOR_OPENING, SOUND_MAX_RIGHT);
2283 else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
2284 PlaySoundStereo(SND_MENU_DOOR_CLOSING, SOUND_MAX_RIGHT);
2287 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2289 for(x=start; x<=DXSIZE; x+=stepsize)
2291 Bitmap *bitmap = new_graphic_info[IMG_MENU_DOOR].bitmap;
2292 GC gc = bitmap->stored_clip_gc;
2294 if (!(door_state & DOOR_NO_DELAY))
2295 WaitUntilDelayReached(&door_delay, door_delay_value);
2297 if (door_state & DOOR_ACTION_1)
2299 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
2300 int j = (DXSIZE - i) / 3;
2302 BlitBitmap(bitmap_db_door, drawto,
2303 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
2304 DXSIZE,DYSIZE - i/2, DX, DY);
2306 ClearRectangle(drawto, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
2308 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2309 BlitBitmapMasked(bitmap, drawto,
2310 DXSIZE, DOOR_GFX_PAGEY1, i, 77,
2311 DX + DXSIZE - i, DY + j);
2312 BlitBitmapMasked(bitmap, drawto,
2313 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
2314 DX + DXSIZE - i, DY + 140 + j);
2315 SetClipOrigin(bitmap, gc, DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
2316 BlitBitmapMasked(bitmap, drawto,
2317 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
2319 BlitBitmapMasked(bitmap, drawto,
2320 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
2323 BlitBitmapMasked(bitmap, drawto,
2324 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2326 BlitBitmapMasked(bitmap, drawto,
2327 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2329 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2330 BlitBitmapMasked(bitmap, drawto,
2331 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2332 DX + DXSIZE - i, DY + 77 + j);
2333 BlitBitmapMasked(bitmap, drawto,
2334 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2335 DX + DXSIZE - i, DY + 203 + j);
2337 redraw_mask |= REDRAW_DOOR_1;
2340 if (door_state & DOOR_ACTION_2)
2342 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
2343 int j = (VXSIZE - i) / 3;
2345 BlitBitmap(bitmap_db_door, drawto,
2346 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
2347 VXSIZE, VYSIZE - i/2, VX, VY);
2349 ClearRectangle(drawto, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
2351 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2352 BlitBitmapMasked(bitmap, drawto,
2353 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
2354 VX + VXSIZE-i, VY+j);
2355 SetClipOrigin(bitmap, gc,
2356 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2357 BlitBitmapMasked(bitmap, drawto,
2358 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
2361 BlitBitmapMasked(bitmap, drawto,
2362 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2363 i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
2364 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2365 BlitBitmapMasked(bitmap, drawto,
2366 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2368 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2370 redraw_mask |= REDRAW_DOOR_2;
2375 if (game_status == MAINMENU)
2380 if (setup.quick_doors)
2382 StopSound(SND_MENU_DOOR_OPENING);
2383 StopSound(SND_MENU_DOOR_CLOSING);
2386 if (door_state & DOOR_ACTION_1)
2387 door1 = door_state & DOOR_ACTION_1;
2388 if (door_state & DOOR_ACTION_2)
2389 door2 = door_state & DOOR_ACTION_2;
2391 return (door1 | door2);
2394 void DrawSpecialEditorDoor()
2396 /* draw bigger toolbox window */
2397 BlitBitmap(new_graphic_info[IMG_MENU_DOOR].bitmap, drawto,
2398 DOOR_GFX_PAGEX7, 0, 108, 56, EX - 4, EY - 12);
2400 redraw_mask |= REDRAW_ALL;
2403 void UndrawSpecialEditorDoor()
2405 /* draw normal tape recorder window */
2406 BlitBitmap(new_graphic_info[IMG_MENU_BACK].bitmap, drawto,
2407 562, 344, 108, 56, EX - 4, EY - 12);
2409 redraw_mask |= REDRAW_ALL;
2413 int ReadPixel(DrawBuffer *bitmap, int x, int y)
2415 XImage *pixel_image;
2416 unsigned long pixel_value;
2418 pixel_image = XGetImage(display, bitmap->drawable,
2419 x, y, 1, 1, AllPlanes, ZPixmap);
2420 pixel_value = XGetPixel(pixel_image, 0, 0);
2422 XDestroyImage(pixel_image);
2428 /* ---------- new tool button stuff ---------------------------------------- */
2430 /* graphic position values for tool buttons */
2431 #define TOOL_BUTTON_YES_XPOS 2
2432 #define TOOL_BUTTON_YES_YPOS 250
2433 #define TOOL_BUTTON_YES_GFX_YPOS 0
2434 #define TOOL_BUTTON_YES_XSIZE 46
2435 #define TOOL_BUTTON_YES_YSIZE 28
2436 #define TOOL_BUTTON_NO_XPOS 52
2437 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2438 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2439 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2440 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2441 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2442 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2443 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2444 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2445 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2446 #define TOOL_BUTTON_PLAYER_XSIZE 30
2447 #define TOOL_BUTTON_PLAYER_YSIZE 30
2448 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2449 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2450 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2451 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2452 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2453 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2454 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2455 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2456 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2457 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2458 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2459 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2460 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2461 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2462 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2463 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2464 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2465 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2466 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2467 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2476 } toolbutton_info[NUM_TOOL_BUTTONS] =
2479 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2480 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2481 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2486 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2487 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2488 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2493 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2494 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2495 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2496 TOOL_CTRL_ID_CONFIRM,
2500 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2501 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2502 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2503 TOOL_CTRL_ID_PLAYER_1,
2507 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2508 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2509 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2510 TOOL_CTRL_ID_PLAYER_2,
2514 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2515 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2516 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2517 TOOL_CTRL_ID_PLAYER_3,
2521 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2522 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2523 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2524 TOOL_CTRL_ID_PLAYER_4,
2529 void CreateToolButtons()
2533 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2535 Bitmap *gd_bitmap = new_graphic_info[IMG_MENU_DOOR].bitmap;
2536 Bitmap *deco_bitmap = None;
2537 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2538 struct GadgetInfo *gi;
2539 unsigned long event_mask;
2540 int gd_xoffset, gd_yoffset;
2541 int gd_x1, gd_x2, gd_y;
2544 event_mask = GD_EVENT_RELEASED;
2546 gd_xoffset = toolbutton_info[i].xpos;
2547 gd_yoffset = toolbutton_info[i].ypos;
2548 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2549 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2550 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2552 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2554 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
2556 getMiniGraphicSource(PLAYER_NR_GFX(IMG_PLAYER1, player_nr),
2557 &deco_bitmap, &deco_x, &deco_y);
2558 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2559 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2562 gi = CreateGadget(GDI_CUSTOM_ID, id,
2563 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2564 GDI_X, DX + toolbutton_info[i].x,
2565 GDI_Y, DY + toolbutton_info[i].y,
2566 GDI_WIDTH, toolbutton_info[i].width,
2567 GDI_HEIGHT, toolbutton_info[i].height,
2568 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2569 GDI_STATE, GD_BUTTON_UNPRESSED,
2570 GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
2571 GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
2572 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
2573 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2574 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2575 GDI_DECORATION_SHIFTING, 1, 1,
2576 GDI_EVENT_MASK, event_mask,
2577 GDI_CALLBACK_ACTION, HandleToolButtons,
2581 Error(ERR_EXIT, "cannot create gadget");
2583 tool_gadget[id] = gi;
2587 void FreeToolButtons()
2591 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2592 FreeGadget(tool_gadget[i]);
2595 static void UnmapToolButtons()
2599 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2600 UnmapGadget(tool_gadget[i]);
2603 static void HandleToolButtons(struct GadgetInfo *gi)
2605 request_gadget_id = gi->custom_id;
2608 int get_next_element(int element)
2612 case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL;
2613 case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY;
2614 case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL;
2615 case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_ACTIVE;
2616 case EL_BD_MAGIC_WALL_FILLING: return EL_BD_MAGIC_WALL_FULL;
2617 case EL_BD_MAGIC_WALL_EMPTYING: return EL_BD_MAGIC_WALL_ACTIVE;
2618 case EL_AMOEBA_DRIPPING: return EL_AMOEBA_WET;
2620 default: return element;
2624 int el2gfx_OLD(int element)
2628 case EL_EMPTY: return -1;
2629 case EL_SAND: return GFX_ERDREICH;
2630 case EL_WALL: return GFX_MAUERWERK;
2631 case EL_WALL_CRUMBLED: return GFX_FELSBODEN;
2632 case EL_ROCK: return GFX_FELSBROCKEN;
2633 case EL_EMERALD: return GFX_EDELSTEIN;
2634 case EL_EXIT_CLOSED: return GFX_AUSGANG_ZU;
2635 case EL_EXIT_OPENING: return GFX_AUSGANG_ACT;
2636 case EL_EXIT_OPEN: return GFX_AUSGANG_AUF;
2637 case EL_SP_EXIT_OPEN: return GFX_SP_EXIT;
2638 case EL_PLAYER1: return GFX_SPIELER1;
2639 case EL_PLAYER2: return GFX_SPIELER2;
2640 case EL_PLAYER3: return GFX_SPIELER3;
2641 case EL_PLAYER4: return GFX_SPIELER4;
2642 case EL_BUG: return GFX_KAEFER;
2643 case EL_BUG_RIGHT: return GFX_KAEFER_RIGHT;
2644 case EL_BUG_UP: return GFX_KAEFER_UP;
2645 case EL_BUG_LEFT: return GFX_KAEFER_LEFT;
2646 case EL_BUG_DOWN: return GFX_KAEFER_DOWN;
2647 case EL_SPACESHIP: return GFX_FLIEGER;
2648 case EL_SPACESHIP_RIGHT: return GFX_FLIEGER_RIGHT;
2649 case EL_SPACESHIP_UP: return GFX_FLIEGER_UP;
2650 case EL_SPACESHIP_LEFT: return GFX_FLIEGER_LEFT;
2651 case EL_SPACESHIP_DOWN: return GFX_FLIEGER_DOWN;
2652 case EL_BD_BUTTERFLY: return GFX_BUTTERFLY;
2653 case EL_BD_BUTTERFLY_RIGHT: return GFX_BUTTERFLY_RIGHT;
2654 case EL_BD_BUTTERFLY_UP: return GFX_BUTTERFLY_UP;
2655 case EL_BD_BUTTERFLY_LEFT: return GFX_BUTTERFLY_LEFT;
2656 case EL_BD_BUTTERFLY_DOWN: return GFX_BUTTERFLY_DOWN;
2657 case EL_BD_FIREFLY: return GFX_FIREFLY;
2658 case EL_BD_FIREFLY_RIGHT: return GFX_FIREFLY_RIGHT;
2659 case EL_BD_FIREFLY_UP: return GFX_FIREFLY_UP;
2660 case EL_BD_FIREFLY_LEFT: return GFX_FIREFLY_LEFT;
2661 case EL_BD_FIREFLY_DOWN: return GFX_FIREFLY_DOWN;
2662 case EL_YAMYAM: return GFX_MAMPFER;
2663 case EL_ROBOT: return GFX_ROBOT;
2664 case EL_STEELWALL: return GFX_BETON;
2665 case EL_DIAMOND: return GFX_DIAMANT;
2666 case EL_QUICKSAND_EMPTY: return GFX_MORAST_LEER;
2667 case EL_QUICKSAND_FULL: return GFX_MORAST_VOLL;
2668 case EL_QUICKSAND_EMPTYING: return GFX_MORAST_LEER;
2669 case EL_AMOEBA_DROP: return GFX_TROPFEN;
2670 case EL_BOMB: return GFX_BOMBE;
2671 case EL_MAGIC_WALL: return GFX_MAGIC_WALL_OFF;
2672 case EL_MAGIC_WALL_ACTIVE: return GFX_MAGIC_WALL_EMPTY;
2673 case EL_MAGIC_WALL_EMPTYING: return GFX_MAGIC_WALL_EMPTY;
2674 case EL_MAGIC_WALL_FULL: return GFX_MAGIC_WALL_FULL;
2675 case EL_MAGIC_WALL_DEAD: return GFX_MAGIC_WALL_DEAD;
2676 case EL_ACID: return GFX_SALZSAEURE;
2677 case EL_AMOEBA_DEAD: return GFX_AMOEBE_TOT;
2678 case EL_AMOEBA_WET: return GFX_AMOEBE_NASS;
2679 case EL_AMOEBA_DRY: return GFX_AMOEBE_NORM;
2680 case EL_AMOEBA_FULL: return GFX_AMOEBE_VOLL;
2681 case EL_BD_AMOEBA: return GFX_AMOEBE_BD;
2682 case EL_AMOEBA_TO_DIAMOND: return GFX_AMOEBA2DIAM;
2683 case EL_AMOEBA_DRIPPING: return GFX_AMOEBE_NASS;
2684 case EL_NUT: return GFX_KOKOSNUSS;
2685 case EL_GAMEOFLIFE: return GFX_LIFE;
2686 case EL_BIOMAZE: return GFX_LIFE_ASYNC;
2687 case EL_DYNAMITE_ACTIVE: return GFX_DYNAMIT;
2688 case EL_STONEBLOCK: return GFX_BADEWANNE;
2689 case EL_ACIDPOOL_TOPLEFT: return GFX_BADEWANNE1;
2690 case EL_ACIDPOOL_TOPRIGHT: return GFX_BADEWANNE2;
2691 case EL_ACIDPOOL_BOTTOMLEFT: return GFX_BADEWANNE3;
2692 case EL_ACIDPOOL_BOTTOM: return GFX_BADEWANNE4;
2693 case EL_ACIDPOOL_BOTTOMRIGHT: return GFX_BADEWANNE5;
2694 case EL_ROBOT_WHEEL: return GFX_ABLENK_AUS;
2695 case EL_ROBOT_WHEEL_ACTIVE: return GFX_ABLENK_EIN;
2696 case EL_KEY1: return GFX_SCHLUESSEL1;
2697 case EL_KEY2: return GFX_SCHLUESSEL2;
2698 case EL_KEY3: return GFX_SCHLUESSEL3;
2699 case EL_KEY4: return GFX_SCHLUESSEL4;
2700 case EL_GATE1: return GFX_PFORTE1;
2701 case EL_GATE2: return GFX_PFORTE2;
2702 case EL_GATE3: return GFX_PFORTE3;
2703 case EL_GATE4: return GFX_PFORTE4;
2704 case EL_GATE1_GRAY: return GFX_PFORTE1X;
2705 case EL_GATE2_GRAY: return GFX_PFORTE2X;
2706 case EL_GATE3_GRAY: return GFX_PFORTE3X;
2707 case EL_GATE4_GRAY: return GFX_PFORTE4X;
2708 case EL_DYNAMITE: return GFX_DYNAMIT_AUS;
2709 case EL_PACMAN: return GFX_PACMAN;
2710 case EL_PACMAN_RIGHT: return GFX_PACMAN_RIGHT;
2711 case EL_PACMAN_UP: return GFX_PACMAN_UP;
2712 case EL_PACMAN_LEFT: return GFX_PACMAN_LEFT;
2713 case EL_PACMAN_DOWN: return GFX_PACMAN_DOWN;
2714 case EL_INVISIBLE_WALL: return GFX_UNSICHTBAR;
2715 case EL_INVISIBLE_WALL_ACTIVE: return GFX_UNSICHTBAR_ON;
2716 case EL_WALL_EMERALD: return GFX_ERZ_EDEL;
2717 case EL_WALL_DIAMOND: return GFX_ERZ_DIAM;
2718 case EL_LAMP: return GFX_BIRNE_AUS;
2719 case EL_LAMP_ACTIVE: return GFX_BIRNE_EIN;
2720 case EL_TIME_ORB_FULL: return GFX_ZEIT_VOLL;
2721 case EL_TIME_ORB_EMPTY: return GFX_ZEIT_LEER;
2722 case EL_WALL_GROWING: return GFX_MAUER_LEBT;
2723 case EL_WALL_GROWING_X: return GFX_MAUER_X;
2724 case EL_WALL_GROWING_Y: return GFX_MAUER_Y;
2725 case EL_WALL_GROWING_XY: return GFX_MAUER_XY;
2726 case EL_BD_DIAMOND: return GFX_EDELSTEIN_BD;
2727 case EL_EMERALD_YELLOW: return GFX_EDELSTEIN_GELB;
2728 case EL_EMERALD_RED: return GFX_EDELSTEIN_ROT;
2729 case EL_EMERALD_PURPLE: return GFX_EDELSTEIN_LILA;
2730 case EL_WALL_BD_DIAMOND: return GFX_ERZ_EDEL_BD;
2731 case EL_WALL_EMERALD_YELLOW: return GFX_ERZ_EDEL_GELB;
2732 case EL_WALL_EMERALD_RED: return GFX_ERZ_EDEL_ROT;
2733 case EL_WALL_EMERALD_PURPLE: return GFX_ERZ_EDEL_LILA;
2734 case EL_DARK_YAMYAM: return GFX_MAMPFER2;
2735 case EL_BD_MAGIC_WALL: return GFX_MAGIC_WALL_BD_OFF;
2736 case EL_BD_MAGIC_WALL_ACTIVE: return GFX_MAGIC_WALL_BD_EMPTY;
2737 case EL_BD_MAGIC_WALL_EMPTYING: return GFX_MAGIC_WALL_BD_EMPTY;
2738 case EL_BD_MAGIC_WALL_FULL: return GFX_MAGIC_WALL_BD_FULL;
2739 case EL_BD_MAGIC_WALL_DEAD: return GFX_MAGIC_WALL_BD_DEAD;
2740 case EL_DYNABOMB_PLAYER1_ACTIVE: return GFX_DYNABOMB;
2741 case EL_DYNABOMB_PLAYER2_ACTIVE: return GFX_DYNABOMB;
2742 case EL_DYNABOMB_PLAYER3_ACTIVE: return GFX_DYNABOMB;
2743 case EL_DYNABOMB_PLAYER4_ACTIVE: return GFX_DYNABOMB;
2744 case EL_DYNABOMB_NR: return GFX_DYNABOMB_NR;
2745 case EL_DYNABOMB_SZ: return GFX_DYNABOMB_SZ;
2746 case EL_DYNABOMB_XL: return GFX_DYNABOMB_XL;
2747 case EL_SOKOBAN_OBJECT: return GFX_SOKOBAN_OBJEKT;
2748 case EL_SOKOBAN_FIELD_EMPTY: return GFX_SOKOBAN_FELD_LEER;
2749 case EL_SOKOBAN_FIELD_FULL: return GFX_SOKOBAN_FELD_VOLL;
2750 case EL_MOLE: return GFX_MOLE;
2751 case EL_PENGUIN: return GFX_PINGUIN;
2752 case EL_PIG: return GFX_SCHWEIN;
2753 case EL_DRAGON: return GFX_DRACHE;
2754 case EL_SATELLITE: return GFX_SONDE;
2755 case EL_ARROW_BLUE_LEFT: return GFX_PFEIL_LEFT;
2756 case EL_ARROW_BLUE_RIGHT: return GFX_PFEIL_RIGHT;
2757 case EL_ARROW_BLUE_UP: return GFX_PFEIL_UP;
2758 case EL_ARROW_BLUE_DOWN: return GFX_PFEIL_DOWN;
2759 case EL_SPEED_PILL: return GFX_SPEED_PILL;
2760 case EL_SP_TERMINAL_ACTIVE: return GFX_SP_TERMINAL;
2761 case EL_SP_BUGGY_BASE_ACTIVE: return GFX_SP_BUG_ACTIVE;
2762 case EL_SP_ZONK: return GFX_SP_ZONK;
2763 /* ^^^^^^^^^^ non-standard position in supaplex graphic set! */
2764 case EL_INVISIBLE_STEELWALL: return GFX_INVISIBLE_STEEL;
2765 case EL_INVISIBLE_STEELWALL_ACTIVE: return GFX_INVISIBLE_STEEL_ON;
2766 case EL_BLACK_ORB: return GFX_BLACK_ORB;
2767 case EL_EM_GATE1: return GFX_EM_GATE_1;
2768 case EL_EM_GATE2: return GFX_EM_GATE_2;
2769 case EL_EM_GATE3: return GFX_EM_GATE_3;
2770 case EL_EM_GATE4: return GFX_EM_GATE_4;
2771 case EL_EM_GATE1_GRAY: return GFX_EM_GATE_1X;
2772 case EL_EM_GATE2_GRAY: return GFX_EM_GATE_2X;
2773 case EL_EM_GATE3_GRAY: return GFX_EM_GATE_3X;
2774 case EL_EM_GATE4_GRAY: return GFX_EM_GATE_4X;
2775 case EL_EM_KEY1_FILE: return GFX_EM_KEY_1;
2776 case EL_EM_KEY2_FILE: return GFX_EM_KEY_2;
2777 case EL_EM_KEY3_FILE: return GFX_EM_KEY_3;
2778 case EL_EM_KEY4_FILE: return GFX_EM_KEY_4;
2779 case EL_EM_KEY1: return GFX_EM_KEY_1;
2780 case EL_EM_KEY2: return GFX_EM_KEY_2;
2781 case EL_EM_KEY3: return GFX_EM_KEY_3;
2782 case EL_EM_KEY4: return GFX_EM_KEY_4;
2783 case EL_PEARL: return GFX_PEARL;
2784 case EL_CRYSTAL: return GFX_CRYSTAL;
2785 case EL_WALL_PEARL: return GFX_WALL_PEARL;
2786 case EL_WALL_CRYSTAL: return GFX_WALL_CRYSTAL;
2787 case EL_DOOR_WHITE: return GFX_DOOR_WHITE;
2788 case EL_DOOR_WHITE_GRAY: return GFX_DOOR_WHITE_GRAY;
2789 case EL_KEY_WHITE: return GFX_KEY_WHITE;
2790 case EL_SHIELD_NORMAL: return GFX_SHIELD_PASSIVE;
2791 case EL_SHIELD_DEADLY: return GFX_SHIELD_ACTIVE;
2792 case EL_EXTRA_TIME: return GFX_EXTRA_TIME;
2793 case EL_SWITCHGATE_OPEN: return GFX_SWITCHGATE_OPEN;
2794 case EL_SWITCHGATE_CLOSED: return GFX_SWITCHGATE_CLOSED;
2795 case EL_SWITCHGATE_SWITCH_UP: return GFX_SWITCHGATE_SWITCH_1;
2796 case EL_SWITCHGATE_SWITCH_DOWN: return GFX_SWITCHGATE_SWITCH_2;
2797 case EL_CONVEYOR_BELT1_LEFT: return GFX_BELT1_LEFT;
2798 case EL_CONVEYOR_BELT1_MIDDLE: return GFX_BELT1_MIDDLE;
2799 case EL_CONVEYOR_BELT1_RIGHT: return GFX_BELT1_RIGHT;
2800 case EL_CONVEYOR_BELT1_LEFT_ACTIVE: return GFX_BELT1_LEFT;
2801 case EL_CONVEYOR_BELT1_MIDDLE_ACTIVE:return GFX_BELT1_MIDDLE;
2802 case EL_CONVEYOR_BELT1_RIGHT_ACTIVE:return GFX_BELT1_RIGHT;
2803 case EL_CONVEYOR_BELT1_SWITCH_LEFT: return GFX_BELT1_SWITCH_LEFT;
2804 case EL_CONVEYOR_BELT1_SWITCH_MIDDLE:return GFX_BELT1_SWITCH_MIDDLE;
2805 case EL_CONVEYOR_BELT1_SWITCH_RIGHT:return GFX_BELT1_SWITCH_RIGHT;
2806 case EL_CONVEYOR_BELT2_LEFT: return GFX_BELT2_LEFT;
2807 case EL_CONVEYOR_BELT2_MIDDLE: return GFX_BELT2_MIDDLE;
2808 case EL_CONVEYOR_BELT2_RIGHT: return GFX_BELT2_RIGHT;
2809 case EL_CONVEYOR_BELT2_LEFT_ACTIVE: return GFX_BELT2_LEFT;
2810 case EL_CONVEYOR_BELT2_MIDDLE_ACTIVE:return GFX_BELT2_MIDDLE;
2811 case EL_CONVEYOR_BELT2_RIGHT_ACTIVE:return GFX_BELT2_RIGHT;
2812 case EL_CONVEYOR_BELT2_SWITCH_LEFT: return GFX_BELT2_SWITCH_LEFT;
2813 case EL_CONVEYOR_BELT2_SWITCH_MIDDLE:return GFX_BELT2_SWITCH_MIDDLE;
2814 case EL_CONVEYOR_BELT2_SWITCH_RIGHT:return GFX_BELT2_SWITCH_RIGHT;
2815 case EL_CONVEYOR_BELT3_LEFT: return GFX_BELT3_LEFT;
2816 case EL_CONVEYOR_BELT3_MIDDLE: return GFX_BELT3_MIDDLE;
2817 case EL_CONVEYOR_BELT3_RIGHT: return GFX_BELT3_RIGHT;
2818 case EL_CONVEYOR_BELT3_LEFT_ACTIVE: return GFX_BELT3_LEFT;
2819 case EL_CONVEYOR_BELT3_MIDDLE_ACTIVE:return GFX_BELT3_MIDDLE;
2820 case EL_CONVEYOR_BELT3_RIGHT_ACTIVE:return GFX_BELT3_RIGHT;
2821 case EL_CONVEYOR_BELT3_SWITCH_LEFT: return GFX_BELT3_SWITCH_LEFT;
2822 case EL_CONVEYOR_BELT3_SWITCH_MIDDLE:return GFX_BELT3_SWITCH_MIDDLE;
2823 case EL_CONVEYOR_BELT3_SWITCH_RIGHT:return GFX_BELT3_SWITCH_RIGHT;
2824 case EL_CONVEYOR_BELT4_LEFT: return GFX_BELT4_LEFT;
2825 case EL_CONVEYOR_BELT4_MIDDLE: return GFX_BELT4_MIDDLE;
2826 case EL_CONVEYOR_BELT4_RIGHT: return GFX_BELT4_RIGHT;
2827 case EL_CONVEYOR_BELT4_LEFT_ACTIVE: return GFX_BELT4_LEFT;
2828 case EL_CONVEYOR_BELT4_MIDDLE_ACTIVE:return GFX_BELT4_MIDDLE;
2829 case EL_CONVEYOR_BELT4_RIGHT_ACTIVE:return GFX_BELT4_RIGHT;
2830 case EL_CONVEYOR_BELT4_SWITCH_LEFT: return GFX_BELT4_SWITCH_LEFT;
2831 case EL_CONVEYOR_BELT4_SWITCH_MIDDLE:return GFX_BELT4_SWITCH_MIDDLE;
2832 case EL_CONVEYOR_BELT4_SWITCH_RIGHT:return GFX_BELT4_SWITCH_RIGHT;
2833 case EL_LANDMINE: return GFX_LANDMINE;
2834 case EL_ENVELOPE: return GFX_ENVELOPE;
2835 case EL_LIGHT_SWITCH: return GFX_LIGHT_SWITCH_OFF;
2836 case EL_LIGHT_SWITCH_ACTIVE: return GFX_LIGHT_SWITCH_ON;
2837 case EL_SIGN_EXCLAMATION: return GFX_SIGN_EXCLAMATION;
2838 case EL_SIGN_RADIOACTIVITY: return GFX_SIGN_RADIOACTIVITY;
2839 case EL_SIGN_STOP: return GFX_SIGN_STOP;
2840 case EL_SIGN_WHEELCHAIR: return GFX_SIGN_WHEELCHAIR;
2841 case EL_SIGN_PARKING: return GFX_SIGN_PARKING;
2842 case EL_SIGN_ONEWAY: return GFX_SIGN_ONEWAY;
2843 case EL_SIGN_HEART: return GFX_SIGN_HEART;
2844 case EL_SIGN_TRIANGLE: return GFX_SIGN_TRIANGLE;
2845 case EL_SIGN_ROUND: return GFX_SIGN_ROUND;
2846 case EL_SIGN_EXIT: return GFX_SIGN_EXIT;
2847 case EL_SIGN_YINYANG: return GFX_SIGN_YINYANG;
2848 case EL_SIGN_OTHER: return GFX_SIGN_OTHER;
2849 case EL_MOLE_LEFT: return GFX_MOLE_LEFT;
2850 case EL_MOLE_RIGHT: return GFX_MOLE_RIGHT;
2851 case EL_MOLE_UP: return GFX_MOLE_UP;
2852 case EL_MOLE_DOWN: return GFX_MOLE_DOWN;
2853 case EL_STEELWALL_SLANTED: return GFX_STEEL_SLANTED;
2854 case EL_INVISIBLE_SAND: return GFX_SAND_INVISIBLE;
2855 case EL_INVISIBLE_SAND_ACTIVE: return GFX_SAND_INVISIBLE_ON;
2856 case EL_DX_UNKNOWN_15: return GFX_DX_UNKNOWN_15;
2857 case EL_DX_UNKNOWN_42: return GFX_DX_UNKNOWN_42;
2858 case EL_TIMEGATE_OPEN: return GFX_TIMEGATE_OPEN;
2859 case EL_TIMEGATE_CLOSED: return GFX_TIMEGATE_CLOSED;
2860 case EL_TIMEGATE_SWITCH_ACTIVE: return GFX_TIMEGATE_SWITCH;
2861 case EL_TIMEGATE_SWITCH: return GFX_TIMEGATE_SWITCH;
2862 case EL_BALLOON: return GFX_BALLOON;
2863 case EL_BALLOON_SEND_LEFT: return GFX_BALLOON_SEND_LEFT;
2864 case EL_BALLOON_SEND_RIGHT: return GFX_BALLOON_SEND_RIGHT;
2865 case EL_BALLOON_SEND_UP: return GFX_BALLOON_SEND_UP;
2866 case EL_BALLOON_SEND_DOWN: return GFX_BALLOON_SEND_DOWN;
2867 case EL_BALLOON_SEND_ANY_DIRECTION: return GFX_BALLOON_SEND_ANY;
2868 case EL_EMC_STEELWALL1: return GFX_EMC_STEEL_WALL_1;
2869 case EL_EMC_STEELWALL2: return GFX_EMC_STEEL_WALL_2;
2870 case EL_EMC_STEELWALL3: return GFX_EMC_STEEL_WALL_3;
2871 case EL_EMC_STEELWALL4: return GFX_EMC_STEEL_WALL_4;
2872 case EL_EMC_WALL_PILLAR_UPPER: return GFX_EMC_WALL_1;
2873 case EL_EMC_WALL_PILLAR_MIDDLE: return GFX_EMC_WALL_2;
2874 case EL_EMC_WALL_PILLAR_LOWER: return GFX_EMC_WALL_3;
2875 case EL_EMC_WALL4: return GFX_EMC_WALL_4;
2876 case EL_EMC_WALL5: return GFX_EMC_WALL_5;
2877 case EL_EMC_WALL6: return GFX_EMC_WALL_6;
2878 case EL_EMC_WALL7: return GFX_EMC_WALL_7;
2879 case EL_EMC_WALL8: return GFX_EMC_WALL_8;
2880 case EL_TUBE_ALL: return GFX_TUBE_CROSS;
2881 case EL_TUBE_VERTICAL: return GFX_TUBE_VERTICAL;
2882 case EL_TUBE_HORIZONTAL: return GFX_TUBE_HORIZONTAL;
2883 case EL_TUBE_VERTICAL_LEFT: return GFX_TUBE_VERT_LEFT;
2884 case EL_TUBE_VERTICAL_RIGHT: return GFX_TUBE_VERT_RIGHT;
2885 case EL_TUBE_HORIZONTAL_UP: return GFX_TUBE_HORIZ_UP;
2886 case EL_TUBE_HORIZONTAL_DOWN: return GFX_TUBE_HORIZ_DOWN;
2887 case EL_TUBE_LEFT_UP: return GFX_TUBE_LEFT_UP;
2888 case EL_TUBE_LEFT_DOWN: return GFX_TUBE_LEFT_DOWN;
2889 case EL_TUBE_RIGHT_UP: return GFX_TUBE_RIGHT_UP;
2890 case EL_TUBE_RIGHT_DOWN: return GFX_TUBE_RIGHT_DOWN;
2891 case EL_SPRING: return GFX_SPRING;
2892 case EL_TRAP: return GFX_TRAP_INACTIVE;
2893 case EL_TRAP_ACTIVE: return GFX_TRAP_ACTIVE;
2894 case EL_BD_WALL: return GFX_BD_WALL;
2895 case EL_BD_ROCK: return GFX_BD_ROCK;
2896 case EL_DX_SUPABOMB: return GFX_DX_SUPABOMB;
2897 case EL_SP_MURPHY_CLONE: return GFX_SP_MURPHY_CLONE;
2901 if (IS_CHAR(element))
2902 return GFX_CHAR_START + (element - EL_CHAR_START);
2903 else if (element >= EL_SP_START && element <= EL_SP_END)
2905 int nr_element = element - EL_SP_START;
2906 int gfx_per_line = 8;
2908 (nr_element / gfx_per_line) * SP_PER_LINE +
2909 (nr_element % gfx_per_line);
2911 return GFX_START_ROCKSSP + nr_graphic;
2919 int el2gfx(int element)
2922 int graphic_OLD = el2gfx_OLD(element);
2927 int graphic_NEW = element_info[element].graphic[GFX_ACTION_DEFAULT];
2930 int graphic_OLD = el2gfx_OLD(element);
2932 if (element >= MAX_ELEMENTS)
2934 Error(ERR_WARN, "el2gfx: element == %d >= MAX_ELEMENTS", element);
2937 if (graphic_NEW != graphic_OLD)
2939 Error(ERR_WARN, "el2gfx: graphic_NEW (%d) != graphic_OLD (%d)",
2940 graphic_NEW, graphic_OLD);
2948 int el2img(int element)
2950 int graphic = element_info[element].graphic[GFX_ACTION_DEFAULT];
2954 Error(ERR_WARN, "element %d -> graphic %d -- probably crashing now...",
2961 int el_dir2img(int element, int direction)
2963 return el_dir_act2img(element, direction, GFX_ACTION_DEFAULT);
2966 int el_dir_act2img(int element, int direction, int action)
2971 printf("el_dir_act2img: THIS SHOULD NEVER HAPPEN: element == %d\n",
2979 printf("el_dir_act2img: THIS SHOULD NEVER HAPPEN: action == %d\n",
2986 action = graphics_action_mapping[action];
2987 direction = MV_DIR_BIT(direction);
2989 return element_info[element].direction_graphic[action][direction];