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(int x, int y, int graphic, int mask_mode)
773 if (IN_SCR_FIELD(x, y))
775 int frame = getGraphicAnimationFrame(graphic, -1);
777 if (mask_mode == USE_MASKING)
778 DrawGraphicThruMask(x, y, graphic, frame);
780 DrawGraphic(x, y, graphic, frame);
784 void DrawGraphicAnimation(int x, int y, int graphic)
786 DrawGraphicAnimationExt(x, y, graphic, NO_MASKING);
790 void getOldGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
792 if (graphic >= 0 && graphic_info[graphic].bitmap != NULL)
794 *bitmap = graphic_info[graphic].bitmap;
795 *x = graphic_info[graphic].src_x;
796 *y = graphic_info[graphic].src_y;
798 else if (graphic >= GFX_START_ROCKSELEMENTS &&
799 graphic <= GFX_END_ROCKSELEMENTS)
801 graphic -= GFX_START_ROCKSELEMENTS;
802 *bitmap = new_graphic_info[IMG_OLD_PIX_ELEMENTS].bitmap;
803 *x = (graphic % GFX_PER_LINE) * TILEX;
804 *y = (graphic / GFX_PER_LINE) * TILEY;
806 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
808 graphic -= GFX_START_ROCKSHEROES;
809 *bitmap = new_graphic_info[IMG_OLD_PIX_HEROES].bitmap;
810 *x = (graphic % HEROES_PER_LINE) * TILEX;
811 *y = (graphic / HEROES_PER_LINE) * TILEY;
813 else if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
815 graphic -= GFX_START_ROCKSSP;
816 *bitmap = new_graphic_info[IMG_OLD_PIX_SP].bitmap;
817 *x = (graphic % SP_PER_LINE) * TILEX;
818 *y = (graphic / SP_PER_LINE) * TILEY;
820 else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
822 graphic -= GFX_START_ROCKSDC;
823 *bitmap = new_graphic_info[IMG_OLD_PIX_DC].bitmap;
824 *x = (graphic % DC_PER_LINE) * TILEX;
825 *y = (graphic / DC_PER_LINE) * TILEY;
827 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
829 graphic -= GFX_START_ROCKSMORE;
830 *bitmap = new_graphic_info[IMG_OLD_PIX_MORE].bitmap;
831 *x = (graphic % MORE_PER_LINE) * TILEX;
832 *y = (graphic / MORE_PER_LINE) * TILEY;
834 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
836 graphic -= GFX_START_ROCKSFONT;
837 *bitmap = new_graphic_info[IMG_OLD_PIX_FONT_EM].bitmap;
838 *x = (graphic % FONT_CHARS_PER_LINE) * TILEX;
839 *y = (graphic / FONT_CHARS_PER_LINE) * TILEY;
843 *bitmap = new_graphic_info[IMG_OLD_PIX_SP].bitmap;
850 void getGraphicSource(int graphic, int frame, Bitmap **bitmap, int *x, int *y)
852 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
853 int offset_x = new_graphic_info[graphic].offset_x;
854 int offset_y = new_graphic_info[graphic].offset_y;
855 int src_x = new_graphic_info[graphic].src_x + frame * offset_x;
856 int src_y = new_graphic_info[graphic].src_y + frame * offset_y;
858 *bitmap = src_bitmap;
863 void DrawGraphic(int x, int y, int graphic, int frame)
866 if (!IN_SCR_FIELD(x, y))
868 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
869 printf("DrawGraphic(): This should never happen!\n");
874 DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic, frame);
879 void DrawOldGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic)
884 getOldGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
885 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
889 void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
896 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
898 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
899 int src_x = new_graphic_info[graphic].src_x;
900 int src_y = new_graphic_info[graphic].src_y;
901 int offset_x = new_graphic_info[graphic].offset_x;
902 int offset_y = new_graphic_info[graphic].offset_y;
904 src_x += frame * offset_x;
905 src_y += frame * offset_y;
908 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
911 void DrawGraphicThruMask(int x, int y, int graphic, int frame)
914 if (!IN_SCR_FIELD(x, y))
916 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
917 printf("DrawGraphicThruMask(): This should never happen!\n");
922 DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY, graphic,
927 void DrawGraphicThruMaskExt(DrawBuffer *d, int dest_x, int dest_y, int graphic,
935 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
936 drawing_gc = src_bitmap->stored_clip_gc;
938 GC drawing_gc = src_bitmap->stored_clip_gc;
939 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
940 int src_x = new_graphic_info[graphic].src_x;
941 int src_y = new_graphic_info[graphic].src_y;
942 int offset_x = new_graphic_info[graphic].offset_x;
943 int offset_y = new_graphic_info[graphic].offset_y;
945 src_x += frame * offset_x;
946 src_y += frame * offset_y;
950 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
951 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dest_x, dest_y);
954 void DrawMiniGraphic(int x, int y, int graphic)
956 DrawMiniGraphicExt(drawto, SX + x * MINI_TILEX,SY + y * MINI_TILEY, graphic);
957 MarkTileDirty(x / 2, y / 2);
960 void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
962 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
964 int mini_starty = src_bitmap->height * 2 / 3;
965 int src_x = mini_startx + new_graphic_info[graphic].src_x / 2;
966 int src_y = mini_starty + new_graphic_info[graphic].src_y / 2;
968 *bitmap = src_bitmap;
973 void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
978 getMiniGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
979 BlitBitmap(src_bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
982 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic, int frame,
983 int cut_mode, int mask_mode)
992 int width = TILEX, height = TILEY;
998 DrawGraphic(x, y, graphic, frame);
1002 if (dx || dy) /* shifted graphic */
1004 if (x < BX1) /* object enters playfield from the left */
1011 else if (x > BX2) /* object enters playfield from the right */
1017 else if (x==BX1 && dx < 0) /* object leaves playfield to the left */
1023 else if (x==BX2 && dx > 0) /* object leaves playfield to the right */
1025 else if (dx) /* general horizontal movement */
1026 MarkTileDirty(x + SIGN(dx), y);
1028 if (y < BY1) /* object enters playfield from the top */
1030 if (cut_mode==CUT_BELOW) /* object completely above top border */
1038 else if (y > BY2) /* object enters playfield from the bottom */
1044 else if (y==BY1 && dy < 0) /* object leaves playfield to the top */
1050 else if (dy > 0 && cut_mode == CUT_ABOVE)
1052 if (y == BY2) /* object completely above bottom border */
1058 MarkTileDirty(x, y + 1);
1059 } /* object leaves playfield to the bottom */
1060 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1062 else if (dy) /* general vertical movement */
1063 MarkTileDirty(x, y + SIGN(dy));
1066 src_bitmap = new_graphic_info[graphic].bitmap;
1067 src_x = new_graphic_info[graphic].src_x;
1068 src_y = new_graphic_info[graphic].src_y;
1069 offset_x = new_graphic_info[graphic].offset_x;
1070 offset_y = new_graphic_info[graphic].offset_y;
1072 drawing_gc = src_bitmap->stored_clip_gc;
1074 src_x += frame * offset_x;
1075 src_y += frame * offset_y;
1080 dest_x = FX + x * TILEX + dx;
1081 dest_y = FY + y * TILEY + dy;
1084 if (!IN_SCR_FIELD(x,y))
1086 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1087 printf("DrawGraphicShifted(): This should never happen!\n");
1092 if (mask_mode == USE_MASKING)
1094 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1095 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
1099 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1105 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
1106 int frame, int cut_mode)
1108 DrawGraphicShifted(x,y, dx,dy, graphic, frame, cut_mode, USE_MASKING);
1112 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1113 int cut_mode, int mask_mode)
1115 int ux = LEVELX(x), uy = LEVELY(y);
1116 int graphic = el2gfx(element);
1117 int phase8 = ABS(MovPos[ux][uy]) / (TILEX / 8);
1118 int phase4 = phase8 / 2;
1119 int phase2 = phase8 / 4;
1120 int dir = MovDir[ux][uy];
1122 if (element == EL_PACMAN || element == EL_BUG || element == EL_SPACESHIP)
1124 graphic += 1 * !phase2;
1128 else if (dir == MV_LEFT)
1130 else if (dir == MV_DOWN)
1133 else if (element == EL_SP_SNIKSNAK)
1136 graphic = GFX_SP_SNIKSNAK_LEFT;
1137 else if (dir == MV_RIGHT)
1138 graphic = GFX_SP_SNIKSNAK_RIGHT;
1139 else if (dir == MV_UP)
1140 graphic = GFX_SP_SNIKSNAK_UP;
1142 graphic = GFX_SP_SNIKSNAK_DOWN;
1144 graphic += (phase8 < 4 ? phase8 : 7 - phase8);
1146 else if (element == EL_SP_ELECTRON)
1148 graphic = GFX2_SP_ELECTRON + getGraphicAnimationPhase(8, 2, ANIM_LOOP);
1150 else if (element == EL_MOLE || element == EL_PENGUIN ||
1151 element == EL_PIG || element == EL_DRAGON)
1154 graphic = (element == EL_MOLE ? GFX_MOLE_LEFT :
1155 element == EL_PENGUIN ? GFX_PINGUIN_LEFT :
1156 element == EL_PIG ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
1157 else if (dir == MV_RIGHT)
1158 graphic = (element == EL_MOLE ? GFX_MOLE_RIGHT :
1159 element == EL_PENGUIN ? GFX_PINGUIN_RIGHT :
1160 element == EL_PIG ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
1161 else if (dir == MV_UP)
1162 graphic = (element == EL_MOLE ? GFX_MOLE_UP :
1163 element == EL_PENGUIN ? GFX_PINGUIN_UP :
1164 element == EL_PIG ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
1166 graphic = (element == EL_MOLE ? GFX_MOLE_DOWN :
1167 element == EL_PENGUIN ? GFX_PINGUIN_DOWN :
1168 element == EL_PIG ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
1172 else if (element == EL_SATELLITE)
1174 graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_LOOP);
1176 else if (element == EL_ACID)
1178 graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_LOOP);
1180 else if (element == EL_BD_BUTTERFLY || element == EL_BD_FIREFLY)
1184 else if (element == EL_BALLOON)
1188 else if ((element == EL_ROCK ||
1189 element == EL_SP_ZONK ||
1190 element == EL_BD_ROCK ||
1191 element == EL_SP_INFOTRON ||
1195 if (uy >= lev_fieldy-1 || !IS_BELT(Feld[ux][uy+1]))
1197 if (element == EL_ROCK ||
1198 element == EL_SP_ZONK ||
1199 element == EL_BD_ROCK)
1202 graphic += (4 - phase4) % 4;
1203 else if (dir == MV_RIGHT)
1206 graphic += phase2 * 2;
1208 else if (element != EL_SP_INFOTRON)
1212 else if (element == EL_MAGIC_WALL_ACTIVE ||
1213 element == EL_MAGIC_WALL_EMPTYING ||
1214 element == EL_BD_MAGIC_WALL_ACTIVE ||
1215 element == EL_BD_MAGIC_WALL_EMPTYING ||
1216 element == EL_MAGIC_WALL_FULL ||
1217 element == EL_BD_MAGIC_WALL_FULL)
1219 graphic += 3 + getGraphicAnimationPhase(4, 4, ANIM_REVERSE);
1221 else if (IS_AMOEBOID(element) || element == EL_AMOEBA_DRIPPING)
1223 graphic = (element == EL_AMOEBA_DEAD ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
1224 graphic += (x + 2 * y + 4) % 4;
1226 else if (element == EL_WALL_GROWING)
1228 boolean links_massiv = FALSE, rechts_massiv = FALSE;
1230 if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
1231 links_massiv = TRUE;
1232 if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
1233 rechts_massiv = TRUE;
1235 if (links_massiv && rechts_massiv)
1236 graphic = GFX_MAUERWERK;
1237 else if (links_massiv)
1238 graphic = GFX_MAUER_R;
1239 else if (rechts_massiv)
1240 graphic = GFX_MAUER_L;
1243 else if ((element == EL_INVISIBLE_STEELWALL ||
1244 element == EL_INVISIBLE_WALL ||
1245 element == EL_INVISIBLE_SAND) && game.light_time_left)
1247 graphic = (element == EL_INVISIBLE_STEELWALL ? GFX_INVISIBLE_STEEL_ON :
1248 element == EL_INVISIBLE_WALL ? GFX_UNSICHTBAR_ON :
1249 GFX_SAND_INVISIBLE_ON);
1254 DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
1255 else if (mask_mode == USE_MASKING)
1256 DrawGraphicThruMask(x, y, graphic);
1258 DrawGraphic(x, y, graphic);
1262 inline static int getFramePosition(int x, int y)
1264 int frame_pos = -1; /* default: global synchronization */
1266 int element = Feld[x][y];
1268 if (element == EL_QUICKSAND_FULL ||
1269 element == EL_MAGIC_WALL_FULL ||
1270 element == EL_BD_MAGIC_WALL_FULL)
1272 else if (IS_MOVING(x, y) || CAN_MOVE(element) || CAN_FALL(element))
1273 frame_pos = ABS(MovPos[x][y]) / (TILEX / 8);
1275 frame_pos = ABS(MovPos[x][y]) / (TILEX / 8);
1281 inline static int getGfxAction(int x, int y)
1283 int gfx_action = GFX_ACTION_DEFAULT;
1286 if (GfxAction[x][y] != GFX_ACTION_DEFAULT)
1287 gfx_action = GfxAction[x][y];
1288 else if (IS_MOVING(x, y))
1289 gfx_action = GFX_ACTION_MOVING;
1291 gfx_action = GfxAction[x][y];
1297 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1298 int cut_mode, int mask_mode)
1300 int ux = LEVELX(x), uy = LEVELY(y);
1301 int move_dir = MovDir[ux][uy];
1302 int move_pos = getFramePosition(ux, uy);
1303 int gfx_action = getGfxAction(ux, uy);
1304 int graphic = el_dir_act2img(element, move_dir, gfx_action);
1305 int frame = getGraphicAnimationFrame(graphic, move_pos);
1307 if (element == EL_WALL_GROWING)
1309 boolean left_stopped = FALSE, right_stopped = FALSE;
1311 if (!IN_LEV_FIELD(ux - 1, uy) || IS_MAUER(Feld[ux - 1][uy]))
1312 left_stopped = TRUE;
1313 if (!IN_LEV_FIELD(ux + 1, uy) || IS_MAUER(Feld[ux + 1][uy]))
1314 right_stopped = TRUE;
1316 if (left_stopped && right_stopped)
1318 else if (left_stopped)
1320 graphic = IMG_WALL_GROWING_ACTIVE_RIGHT;
1321 frame = new_graphic_info[graphic].anim_frames - 1;
1323 else if (right_stopped)
1325 graphic = IMG_WALL_GROWING_ACTIVE_LEFT;
1326 frame = new_graphic_info[graphic].anim_frames - 1;
1329 else if (IS_AMOEBOID(element) || element == EL_AMOEBA_DRIPPING)
1331 graphic = (element == EL_BD_AMOEBA ? IMG_BD_AMOEBA_PART1 :
1332 element == EL_AMOEBA_WET ? IMG_AMOEBA_WET_PART1 :
1333 element == EL_AMOEBA_DRY ? IMG_AMOEBA_DRY_PART1 :
1334 element == EL_AMOEBA_FULL ? IMG_AMOEBA_FULL_PART1 :
1335 IMG_AMOEBA_DEAD_PART1);
1337 graphic += (x + 2 * y + 4) % 4;
1341 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
1342 else if (mask_mode == USE_MASKING)
1343 DrawGraphicThruMask(x, y, graphic, frame);
1345 DrawGraphic(x, y, graphic, frame);
1348 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1349 int cut_mode, int mask_mode)
1351 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1352 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1353 cut_mode, mask_mode);
1356 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1359 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1362 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1365 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1369 void DrawOldScreenElementThruMask(int x, int y, int element)
1371 DrawOldScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1374 void DrawScreenElementThruMask(int x, int y, int element)
1376 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1380 void DrawLevelElementThruMask(int x, int y, int element)
1382 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1385 void DrawLevelFieldThruMask(int x, int y)
1387 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1390 void DrawCrumbledSand(int x, int y)
1394 int i, width, height, cx,cy;
1395 int ux = LEVELX(x), uy = LEVELY(y);
1396 int element, graphic;
1398 static int xy[4][2] =
1406 if (!IN_LEV_FIELD(ux, uy))
1409 element = Feld[ux][uy];
1411 if (element == EL_SAND ||
1412 element == EL_LANDMINE ||
1413 element == EL_TRAP ||
1414 element == EL_TRAP_ACTIVE)
1416 if (!IN_SCR_FIELD(x, y))
1419 graphic = IMG_SAND_CRUMBLED;
1421 src_bitmap = new_graphic_info[graphic].bitmap;
1422 src_x = new_graphic_info[graphic].src_x;
1423 src_y = new_graphic_info[graphic].src_y;
1429 uxx = ux + xy[i][0];
1430 uyy = uy + xy[i][1];
1431 if (!IN_LEV_FIELD(uxx, uyy))
1432 element = EL_STEELWALL;
1434 element = Feld[uxx][uyy];
1436 if (element == EL_SAND ||
1437 element == EL_LANDMINE ||
1438 element == EL_TRAP ||
1439 element == EL_TRAP_ACTIVE)
1442 if (i == 1 || i == 2)
1446 cx = (i == 2 ? TILEX - snip : 0);
1454 cy = (i == 3 ? TILEY - snip : 0);
1457 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1458 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1461 MarkTileDirty(x, y);
1465 graphic = IMG_SAND_CRUMBLED;
1467 src_bitmap = new_graphic_info[graphic].bitmap;
1468 src_x = new_graphic_info[graphic].src_x;
1469 src_y = new_graphic_info[graphic].src_y;
1473 int xx, yy, uxx, uyy;
1477 uxx = ux + xy[i][0];
1478 uyy = uy + xy[i][1];
1480 if (!IN_LEV_FIELD(uxx, uyy) ||
1481 (Feld[uxx][uyy] != EL_SAND &&
1482 Feld[uxx][uyy] != EL_LANDMINE &&
1483 Feld[uxx][uyy] != EL_TRAP &&
1484 Feld[uxx][uyy] != EL_TRAP_ACTIVE) ||
1485 !IN_SCR_FIELD(xx, yy))
1488 if (i == 1 || i == 2)
1492 cx = (i == 1 ? TILEX - snip : 0);
1500 cy = (i==0 ? TILEY-snip : 0);
1503 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1504 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1506 MarkTileDirty(xx, yy);
1511 void DrawScreenElement(int x, int y, int element)
1513 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1514 DrawCrumbledSand(x, y);
1517 void DrawLevelElement(int x, int y, int element)
1519 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1520 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1523 void DrawScreenField(int x, int y)
1525 int ux = LEVELX(x), uy = LEVELY(y);
1526 int element, content;
1528 if (!IN_LEV_FIELD(ux, uy))
1530 if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
1533 element = BorderElement;
1535 DrawScreenElement(x, y, element);
1539 element = Feld[ux][uy];
1540 content = Store[ux][uy];
1542 if (IS_MOVING(ux, uy))
1544 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1545 boolean cut_mode = NO_CUTTING;
1547 if (element == EL_QUICKSAND_EMPTYING ||
1548 element == EL_MAGIC_WALL_EMPTYING ||
1549 element == EL_BD_MAGIC_WALL_EMPTYING ||
1550 element == EL_AMOEBA_DRIPPING)
1551 cut_mode = CUT_ABOVE;
1552 else if (element == EL_QUICKSAND_FILLING ||
1553 element == EL_MAGIC_WALL_FILLING ||
1554 element == EL_BD_MAGIC_WALL_FILLING)
1555 cut_mode = CUT_BELOW;
1557 if (cut_mode == CUT_ABOVE)
1558 DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1560 DrawScreenElement(x, y, EL_EMPTY);
1563 DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1564 else if (cut_mode == NO_CUTTING)
1565 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1567 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], content, cut_mode);
1569 if (content == EL_ACID)
1570 DrawLevelElementThruMask(ux, uy + 1, EL_ACID);
1572 else if (IS_BLOCKED(ux, uy))
1577 boolean cut_mode = NO_CUTTING;
1578 int element_old, content_old;
1580 Blocked2Moving(ux, uy, &oldx, &oldy);
1583 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1584 MovDir[oldx][oldy] == MV_RIGHT);
1586 element_old = Feld[oldx][oldy];
1587 content_old = Store[oldx][oldy];
1589 if (element_old == EL_QUICKSAND_EMPTYING ||
1590 element_old == EL_MAGIC_WALL_EMPTYING ||
1591 element_old == EL_BD_MAGIC_WALL_EMPTYING ||
1592 element_old == EL_AMOEBA_DRIPPING)
1593 cut_mode = CUT_ABOVE;
1595 DrawScreenElement(x, y, EL_EMPTY);
1598 DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
1600 else if (cut_mode == NO_CUTTING)
1601 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
1604 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
1607 else if (IS_DRAWABLE(element))
1608 DrawScreenElement(x, y, element);
1610 DrawScreenElement(x, y, EL_EMPTY);
1613 void DrawLevelField(int x, int y)
1615 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1616 DrawScreenField(SCREENX(x), SCREENY(y));
1617 else if (IS_MOVING(x, y))
1621 Moving2Blocked(x, y, &newx, &newy);
1622 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1623 DrawScreenField(SCREENX(newx), SCREENY(newy));
1625 else if (IS_BLOCKED(x, y))
1629 Blocked2Moving(x, y, &oldx, &oldy);
1630 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1631 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1635 void DrawMiniElement(int x, int y, int element)
1639 graphic = el2img(element);
1640 DrawMiniGraphic(x, y, graphic);
1643 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1645 int x = sx + scroll_x, y = sy + scroll_y;
1647 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1648 DrawMiniElement(sx, sy, EL_EMPTY);
1649 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1650 DrawMiniElement(sx, sy, Feld[x][y]);
1653 int steel_type, steel_position;
1656 { IMG_STEELWALL_TOPLEFT, IMG_INVISIBLE_STEELWALL_TOPLEFT },
1657 { IMG_STEELWALL_TOPRIGHT, IMG_INVISIBLE_STEELWALL_TOPRIGHT },
1658 { IMG_STEELWALL_BOTTOMLEFT, IMG_INVISIBLE_STEELWALL_BOTTOMLEFT },
1659 { IMG_STEELWALL_BOTTOMRIGHT, IMG_INVISIBLE_STEELWALL_BOTTOMRIGHT },
1660 { IMG_STEELWALL_VERTICAL, IMG_INVISIBLE_STEELWALL_VERTICAL },
1661 { IMG_STEELWALL_HORIZONTAL, IMG_INVISIBLE_STEELWALL_HORIZONTAL }
1664 steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
1665 steel_position = (x == -1 && y == -1 ? 0 :
1666 x == lev_fieldx && y == -1 ? 1 :
1667 x == -1 && y == lev_fieldy ? 2 :
1668 x == lev_fieldx && y == lev_fieldy ? 3 :
1669 x == -1 || x == lev_fieldx ? 4 :
1670 y == -1 || y == lev_fieldy ? 5 : -1);
1672 if (steel_position != -1)
1673 DrawMiniGraphic(sx, sy, border[steel_position][steel_type]);
1677 void getMicroGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1679 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
1680 int mini_startx = src_bitmap->width * 3 / 4;
1681 int mini_starty = src_bitmap->height * 2 / 3;
1682 int src_x = mini_startx + new_graphic_info[graphic].src_x / 8;
1683 int src_y = mini_starty + new_graphic_info[graphic].src_y / 8;
1685 *bitmap = src_bitmap;
1690 void DrawMicroElement(int xpos, int ypos, int element)
1696 if (element == EL_EMPTY)
1699 graphic = el2img(element);
1701 getMicroGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1702 BlitBitmap(src_bitmap, drawto, src_x, src_y, MICRO_TILEX, MICRO_TILEY,
1712 for(x=BX1; x<=BX2; x++)
1713 for(y=BY1; y<=BY2; y++)
1714 DrawScreenField(x, y);
1716 redraw_mask |= REDRAW_FIELD;
1719 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1723 for(x=0; x<size_x; x++)
1724 for(y=0; y<size_y; y++)
1725 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1727 redraw_mask |= REDRAW_FIELD;
1730 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1734 ClearRectangle(drawto, xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
1736 if (lev_fieldx < STD_LEV_FIELDX)
1737 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1738 if (lev_fieldy < STD_LEV_FIELDY)
1739 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1741 xpos += MICRO_TILEX;
1742 ypos += MICRO_TILEY;
1744 for(x=-1; x<=STD_LEV_FIELDX; x++)
1746 for(y=-1; y<=STD_LEV_FIELDY; y++)
1748 int lx = from_x + x, ly = from_y + y;
1750 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1751 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1753 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1)
1754 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1759 redraw_mask |= REDRAW_MICROLEVEL;
1762 #define MICROLABEL_EMPTY 0
1763 #define MICROLABEL_LEVEL_NAME 1
1764 #define MICROLABEL_CREATED_BY 2
1765 #define MICROLABEL_LEVEL_AUTHOR 3
1766 #define MICROLABEL_IMPORTED_FROM 4
1767 #define MICROLABEL_LEVEL_IMPORT_INFO 5
1769 #define MAX_MICROLABEL_SIZE (SXSIZE / FONT4_XSIZE)
1771 static void DrawMicroLevelLabelExt(int mode)
1773 char label_text[MAX_MICROLABEL_SIZE + 1];
1775 ClearRectangle(drawto, SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
1777 strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
1778 mode == MICROLABEL_CREATED_BY ? "created by" :
1779 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
1780 mode == MICROLABEL_IMPORTED_FROM ? "imported from" :
1781 mode == MICROLABEL_LEVEL_IMPORT_INFO ?
1782 leveldir_current->imported_from : ""),
1783 MAX_MICROLABEL_SIZE);
1784 label_text[MAX_MICROLABEL_SIZE] = '\0';
1786 if (strlen(label_text) > 0)
1788 int lxpos = SX + (SXSIZE - strlen(label_text) * FONT4_XSIZE) / 2;
1789 int lypos = MICROLABEL_YPOS;
1791 DrawText(lxpos, lypos, label_text, FS_SMALL, FC_SPECIAL2);
1794 redraw_mask |= REDRAW_MICROLEVEL;
1797 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1799 static unsigned long scroll_delay = 0;
1800 static unsigned long label_delay = 0;
1801 static int from_x, from_y, scroll_direction;
1802 static int label_state, label_counter;
1806 from_x = from_y = 0;
1807 scroll_direction = MV_RIGHT;
1811 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1812 DrawMicroLevelLabelExt(label_state);
1814 /* initialize delay counters */
1815 DelayReached(&scroll_delay, 0);
1816 DelayReached(&label_delay, 0);
1821 /* scroll micro level, if needed */
1822 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1823 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1825 switch (scroll_direction)
1831 scroll_direction = MV_UP;
1835 if (from_x < lev_fieldx - STD_LEV_FIELDX)
1838 scroll_direction = MV_DOWN;
1845 scroll_direction = MV_RIGHT;
1849 if (from_y < lev_fieldy - STD_LEV_FIELDY)
1852 scroll_direction = MV_LEFT;
1859 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1862 /* redraw micro level label, if needed */
1863 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1864 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1865 strcmp(level.author, leveldir_current->name) != 0 &&
1866 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1868 int max_label_counter = 23;
1870 if (leveldir_current->imported_from != NULL)
1871 max_label_counter += 14;
1873 label_counter = (label_counter + 1) % max_label_counter;
1874 label_state = (label_counter >= 0 && label_counter <= 7 ?
1875 MICROLABEL_LEVEL_NAME :
1876 label_counter >= 9 && label_counter <= 12 ?
1877 MICROLABEL_CREATED_BY :
1878 label_counter >= 14 && label_counter <= 21 ?
1879 MICROLABEL_LEVEL_AUTHOR :
1880 label_counter >= 23 && label_counter <= 26 ?
1881 MICROLABEL_IMPORTED_FROM :
1882 label_counter >= 28 && label_counter <= 35 ?
1883 MICROLABEL_LEVEL_IMPORT_INFO : MICROLABEL_EMPTY);
1884 DrawMicroLevelLabelExt(label_state);
1888 int REQ_in_range(int x, int y)
1890 if (y > DY+249 && y < DY+278)
1892 if (x > DX+1 && x < DX+48)
1894 else if (x > DX+51 && x < DX+98)
1900 #define MAX_REQUEST_LINES 13
1901 #define MAX_REQUEST_LINE_LEN 7
1903 boolean Request(char *text, unsigned int req_state)
1905 int mx, my, ty, result = -1;
1906 unsigned int old_door_state;
1908 #if defined(PLATFORM_UNIX)
1909 /* pause network game while waiting for request to answer */
1910 if (options.network &&
1911 game_status == PLAYING &&
1912 req_state & REQUEST_WAIT_FOR)
1913 SendToServer_PausePlaying();
1916 old_door_state = GetDoorState();
1920 CloseDoor(DOOR_CLOSE_1);
1922 /* save old door content */
1923 BlitBitmap(bitmap_db_door, bitmap_db_door,
1924 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
1925 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
1927 /* clear door drawing field */
1928 ClearRectangle(drawto, DX, DY, DXSIZE, DYSIZE);
1930 /* write text for request */
1931 for(ty=0; ty < MAX_REQUEST_LINES; ty++)
1933 char text_line[MAX_REQUEST_LINE_LEN + 1];
1939 for(tl=0,tx=0; tx < MAX_REQUEST_LINE_LEN; tl++,tx++)
1942 if (!tc || tc == ' ')
1953 strncpy(text_line, text, tl);
1956 DrawTextExt(drawto, DX + 50 - (tl * 14)/2, DY + 8 + ty * 16,
1957 text_line, FS_SMALL, FC_YELLOW);
1959 text += tl + (tc == ' ' ? 1 : 0);
1962 if (req_state & REQ_ASK)
1964 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
1965 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
1967 else if (req_state & REQ_CONFIRM)
1969 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
1971 else if (req_state & REQ_PLAYER)
1973 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
1974 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
1975 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
1976 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
1979 /* copy request gadgets to door backbuffer */
1980 BlitBitmap(drawto, bitmap_db_door,
1981 DX, DY, DXSIZE, DYSIZE,
1982 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1984 OpenDoor(DOOR_OPEN_1);
1990 if (!(req_state & REQUEST_WAIT_FOR))
1993 if (game_status != MAINMENU)
1996 button_status = MB_RELEASED;
1998 request_gadget_id = -1;
2010 case EVENT_BUTTONPRESS:
2011 case EVENT_BUTTONRELEASE:
2012 case EVENT_MOTIONNOTIFY:
2014 if (event.type == EVENT_MOTIONNOTIFY)
2016 if (!PointerInWindow(window))
2017 continue; /* window and pointer are on different screens */
2022 motion_status = TRUE;
2023 mx = ((MotionEvent *) &event)->x;
2024 my = ((MotionEvent *) &event)->y;
2028 motion_status = FALSE;
2029 mx = ((ButtonEvent *) &event)->x;
2030 my = ((ButtonEvent *) &event)->y;
2031 if (event.type == EVENT_BUTTONPRESS)
2032 button_status = ((ButtonEvent *) &event)->button;
2034 button_status = MB_RELEASED;
2037 /* this sets 'request_gadget_id' */
2038 HandleGadgets(mx, my, button_status);
2040 switch(request_gadget_id)
2042 case TOOL_CTRL_ID_YES:
2045 case TOOL_CTRL_ID_NO:
2048 case TOOL_CTRL_ID_CONFIRM:
2049 result = TRUE | FALSE;
2052 case TOOL_CTRL_ID_PLAYER_1:
2055 case TOOL_CTRL_ID_PLAYER_2:
2058 case TOOL_CTRL_ID_PLAYER_3:
2061 case TOOL_CTRL_ID_PLAYER_4:
2072 case EVENT_KEYPRESS:
2073 switch(GetEventKey((KeyEvent *)&event, TRUE))
2086 if (req_state & REQ_PLAYER)
2090 case EVENT_KEYRELEASE:
2091 ClearPlayerAction();
2095 HandleOtherEvents(&event);
2099 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2101 int joy = AnyJoystick();
2103 if (joy & JOY_BUTTON_1)
2105 else if (joy & JOY_BUTTON_2)
2111 /* don't eat all CPU time */
2115 if (game_status != MAINMENU)
2120 if (!(req_state & REQ_STAY_OPEN))
2122 CloseDoor(DOOR_CLOSE_1);
2124 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
2126 BlitBitmap(bitmap_db_door, bitmap_db_door,
2127 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
2128 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
2129 OpenDoor(DOOR_OPEN_1);
2135 #if defined(PLATFORM_UNIX)
2136 /* continue network game after request */
2137 if (options.network &&
2138 game_status == PLAYING &&
2139 req_state & REQUEST_WAIT_FOR)
2140 SendToServer_ContinuePlaying();
2146 unsigned int OpenDoor(unsigned int door_state)
2148 unsigned int new_door_state;
2150 if (door_state & DOOR_COPY_BACK)
2152 BlitBitmap(bitmap_db_door, bitmap_db_door,
2153 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
2154 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2155 door_state &= ~DOOR_COPY_BACK;
2158 new_door_state = MoveDoor(door_state);
2160 return(new_door_state);
2163 unsigned int CloseDoor(unsigned int door_state)
2165 unsigned int new_door_state;
2167 BlitBitmap(backbuffer, bitmap_db_door,
2168 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2169 BlitBitmap(backbuffer, bitmap_db_door,
2170 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2172 new_door_state = MoveDoor(door_state);
2174 return(new_door_state);
2177 unsigned int GetDoorState()
2179 return MoveDoor(DOOR_GET_STATE);
2182 unsigned int SetDoorState(unsigned int door_state)
2184 return MoveDoor(door_state | DOOR_SET_STATE);
2187 unsigned int MoveDoor(unsigned int door_state)
2189 static int door1 = DOOR_OPEN_1;
2190 static int door2 = DOOR_CLOSE_2;
2191 static unsigned long door_delay = 0;
2192 int x, start, stepsize = 2;
2193 unsigned long door_delay_value = stepsize * 5;
2195 if (door_state == DOOR_GET_STATE)
2196 return(door1 | door2);
2198 if (door_state & DOOR_SET_STATE)
2200 if (door_state & DOOR_ACTION_1)
2201 door1 = door_state & DOOR_ACTION_1;
2202 if (door_state & DOOR_ACTION_2)
2203 door2 = door_state & DOOR_ACTION_2;
2205 return(door1 | door2);
2208 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2209 door_state &= ~DOOR_OPEN_1;
2210 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2211 door_state &= ~DOOR_CLOSE_1;
2212 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2213 door_state &= ~DOOR_OPEN_2;
2214 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2215 door_state &= ~DOOR_CLOSE_2;
2217 if (setup.quick_doors)
2220 door_delay_value = 0;
2221 StopSound(SND_MENU_DOOR_OPENING);
2222 StopSound(SND_MENU_DOOR_CLOSING);
2225 if (door_state & DOOR_ACTION)
2227 if (!(door_state & DOOR_NO_DELAY))
2229 /* opening door sound has priority over simultaneously closing door */
2230 if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
2231 PlaySoundStereo(SND_MENU_DOOR_OPENING, SOUND_MAX_RIGHT);
2232 else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
2233 PlaySoundStereo(SND_MENU_DOOR_CLOSING, SOUND_MAX_RIGHT);
2236 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2238 for(x=start; x<=DXSIZE; x+=stepsize)
2240 Bitmap *bitmap = new_graphic_info[IMG_MENU_DOOR].bitmap;
2241 GC gc = bitmap->stored_clip_gc;
2243 WaitUntilDelayReached(&door_delay, door_delay_value);
2245 if (door_state & DOOR_ACTION_1)
2247 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
2248 int j = (DXSIZE - i) / 3;
2250 BlitBitmap(bitmap_db_door, drawto,
2251 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
2252 DXSIZE,DYSIZE - i/2, DX, DY);
2254 ClearRectangle(drawto, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
2256 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2257 BlitBitmapMasked(bitmap, drawto,
2258 DXSIZE, DOOR_GFX_PAGEY1, i, 77,
2259 DX + DXSIZE - i, DY + j);
2260 BlitBitmapMasked(bitmap, drawto,
2261 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
2262 DX + DXSIZE - i, DY + 140 + j);
2263 SetClipOrigin(bitmap, gc, DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
2264 BlitBitmapMasked(bitmap, drawto,
2265 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
2267 BlitBitmapMasked(bitmap, drawto,
2268 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
2271 BlitBitmapMasked(bitmap, drawto,
2272 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2274 BlitBitmapMasked(bitmap, drawto,
2275 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2277 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2278 BlitBitmapMasked(bitmap, drawto,
2279 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2280 DX + DXSIZE - i, DY + 77 + j);
2281 BlitBitmapMasked(bitmap, drawto,
2282 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2283 DX + DXSIZE - i, DY + 203 + j);
2285 redraw_mask |= REDRAW_DOOR_1;
2288 if (door_state & DOOR_ACTION_2)
2290 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
2291 int j = (VXSIZE - i) / 3;
2293 BlitBitmap(bitmap_db_door, drawto,
2294 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
2295 VXSIZE, VYSIZE - i/2, VX, VY);
2297 ClearRectangle(drawto, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
2299 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2300 BlitBitmapMasked(bitmap, drawto,
2301 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
2302 VX + VXSIZE-i, VY+j);
2303 SetClipOrigin(bitmap, gc,
2304 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2305 BlitBitmapMasked(bitmap, drawto,
2306 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
2309 BlitBitmapMasked(bitmap, drawto,
2310 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2311 i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
2312 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2313 BlitBitmapMasked(bitmap, drawto,
2314 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2316 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2318 redraw_mask |= REDRAW_DOOR_2;
2323 if (game_status == MAINMENU)
2328 if (setup.quick_doors)
2330 StopSound(SND_MENU_DOOR_OPENING);
2331 StopSound(SND_MENU_DOOR_CLOSING);
2334 if (door_state & DOOR_ACTION_1)
2335 door1 = door_state & DOOR_ACTION_1;
2336 if (door_state & DOOR_ACTION_2)
2337 door2 = door_state & DOOR_ACTION_2;
2339 return (door1 | door2);
2342 void DrawSpecialEditorDoor()
2344 /* draw bigger toolbox window */
2345 BlitBitmap(new_graphic_info[IMG_MENU_DOOR].bitmap, drawto,
2346 DOOR_GFX_PAGEX7, 0, 108, 56, EX - 4, EY - 12);
2348 redraw_mask |= REDRAW_ALL;
2351 void UndrawSpecialEditorDoor()
2353 /* draw normal tape recorder window */
2354 BlitBitmap(new_graphic_info[IMG_MENU_BACK].bitmap, drawto,
2355 562, 344, 108, 56, EX - 4, EY - 12);
2357 redraw_mask |= REDRAW_ALL;
2361 int ReadPixel(DrawBuffer *bitmap, int x, int y)
2363 XImage *pixel_image;
2364 unsigned long pixel_value;
2366 pixel_image = XGetImage(display, bitmap->drawable,
2367 x, y, 1, 1, AllPlanes, ZPixmap);
2368 pixel_value = XGetPixel(pixel_image, 0, 0);
2370 XDestroyImage(pixel_image);
2376 /* ---------- new tool button stuff ---------------------------------------- */
2378 /* graphic position values for tool buttons */
2379 #define TOOL_BUTTON_YES_XPOS 2
2380 #define TOOL_BUTTON_YES_YPOS 250
2381 #define TOOL_BUTTON_YES_GFX_YPOS 0
2382 #define TOOL_BUTTON_YES_XSIZE 46
2383 #define TOOL_BUTTON_YES_YSIZE 28
2384 #define TOOL_BUTTON_NO_XPOS 52
2385 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2386 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2387 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2388 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2389 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2390 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2391 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2392 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2393 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2394 #define TOOL_BUTTON_PLAYER_XSIZE 30
2395 #define TOOL_BUTTON_PLAYER_YSIZE 30
2396 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2397 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2398 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2399 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2400 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2401 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2402 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2403 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2404 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2405 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2406 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2407 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2408 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2409 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2410 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2411 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2412 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2413 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2414 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2415 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2424 } toolbutton_info[NUM_TOOL_BUTTONS] =
2427 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2428 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2429 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2434 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2435 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2436 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2441 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2442 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2443 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2444 TOOL_CTRL_ID_CONFIRM,
2448 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2449 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2450 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2451 TOOL_CTRL_ID_PLAYER_1,
2455 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2456 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2457 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2458 TOOL_CTRL_ID_PLAYER_2,
2462 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2463 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2464 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2465 TOOL_CTRL_ID_PLAYER_3,
2469 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2470 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2471 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2472 TOOL_CTRL_ID_PLAYER_4,
2477 void CreateToolButtons()
2481 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2483 Bitmap *gd_bitmap = new_graphic_info[IMG_MENU_DOOR].bitmap;
2484 Bitmap *deco_bitmap = None;
2485 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2486 struct GadgetInfo *gi;
2487 unsigned long event_mask;
2488 int gd_xoffset, gd_yoffset;
2489 int gd_x1, gd_x2, gd_y;
2492 event_mask = GD_EVENT_RELEASED;
2494 gd_xoffset = toolbutton_info[i].xpos;
2495 gd_yoffset = toolbutton_info[i].ypos;
2496 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2497 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2498 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2500 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2502 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
2504 getMiniGraphicSource(PLAYER_NR_GFX(IMG_PLAYER1, player_nr),
2505 &deco_bitmap, &deco_x, &deco_y);
2506 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2507 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2510 gi = CreateGadget(GDI_CUSTOM_ID, id,
2511 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2512 GDI_X, DX + toolbutton_info[i].x,
2513 GDI_Y, DY + toolbutton_info[i].y,
2514 GDI_WIDTH, toolbutton_info[i].width,
2515 GDI_HEIGHT, toolbutton_info[i].height,
2516 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2517 GDI_STATE, GD_BUTTON_UNPRESSED,
2518 GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
2519 GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
2520 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
2521 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2522 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2523 GDI_DECORATION_SHIFTING, 1, 1,
2524 GDI_EVENT_MASK, event_mask,
2525 GDI_CALLBACK_ACTION, HandleToolButtons,
2529 Error(ERR_EXIT, "cannot create gadget");
2531 tool_gadget[id] = gi;
2535 static void UnmapToolButtons()
2539 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2540 UnmapGadget(tool_gadget[i]);
2543 static void HandleToolButtons(struct GadgetInfo *gi)
2545 request_gadget_id = gi->custom_id;
2548 int get_next_element(int element)
2552 case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL;
2553 case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY;
2554 case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL;
2555 case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_ACTIVE;
2556 case EL_BD_MAGIC_WALL_FILLING: return EL_BD_MAGIC_WALL_FULL;
2557 case EL_BD_MAGIC_WALL_EMPTYING: return EL_BD_MAGIC_WALL_ACTIVE;
2558 case EL_AMOEBA_DRIPPING: return EL_AMOEBA_WET;
2560 default: return element;
2564 int el2gfx_OLD(int element)
2568 case EL_EMPTY: return -1;
2569 case EL_SAND: return GFX_ERDREICH;
2570 case EL_WALL: return GFX_MAUERWERK;
2571 case EL_WALL_CRUMBLED: return GFX_FELSBODEN;
2572 case EL_ROCK: return GFX_FELSBROCKEN;
2573 case EL_EMERALD: return GFX_EDELSTEIN;
2574 case EL_EXIT_CLOSED: return GFX_AUSGANG_ZU;
2575 case EL_EXIT_OPENING: return GFX_AUSGANG_ACT;
2576 case EL_EXIT_OPEN: return GFX_AUSGANG_AUF;
2577 case EL_SP_EXIT_OPEN: return GFX_SP_EXIT;
2578 case EL_PLAYER1: return GFX_SPIELER1;
2579 case EL_PLAYER2: return GFX_SPIELER2;
2580 case EL_PLAYER3: return GFX_SPIELER3;
2581 case EL_PLAYER4: return GFX_SPIELER4;
2582 case EL_BUG: return GFX_KAEFER;
2583 case EL_BUG_RIGHT: return GFX_KAEFER_RIGHT;
2584 case EL_BUG_UP: return GFX_KAEFER_UP;
2585 case EL_BUG_LEFT: return GFX_KAEFER_LEFT;
2586 case EL_BUG_DOWN: return GFX_KAEFER_DOWN;
2587 case EL_SPACESHIP: return GFX_FLIEGER;
2588 case EL_SPACESHIP_RIGHT: return GFX_FLIEGER_RIGHT;
2589 case EL_SPACESHIP_UP: return GFX_FLIEGER_UP;
2590 case EL_SPACESHIP_LEFT: return GFX_FLIEGER_LEFT;
2591 case EL_SPACESHIP_DOWN: return GFX_FLIEGER_DOWN;
2592 case EL_BD_BUTTERFLY: return GFX_BUTTERFLY;
2593 case EL_BD_BUTTERFLY_RIGHT: return GFX_BUTTERFLY_RIGHT;
2594 case EL_BD_BUTTERFLY_UP: return GFX_BUTTERFLY_UP;
2595 case EL_BD_BUTTERFLY_LEFT: return GFX_BUTTERFLY_LEFT;
2596 case EL_BD_BUTTERFLY_DOWN: return GFX_BUTTERFLY_DOWN;
2597 case EL_BD_FIREFLY: return GFX_FIREFLY;
2598 case EL_BD_FIREFLY_RIGHT: return GFX_FIREFLY_RIGHT;
2599 case EL_BD_FIREFLY_UP: return GFX_FIREFLY_UP;
2600 case EL_BD_FIREFLY_LEFT: return GFX_FIREFLY_LEFT;
2601 case EL_BD_FIREFLY_DOWN: return GFX_FIREFLY_DOWN;
2602 case EL_YAMYAM: return GFX_MAMPFER;
2603 case EL_ROBOT: return GFX_ROBOT;
2604 case EL_STEELWALL: return GFX_BETON;
2605 case EL_DIAMOND: return GFX_DIAMANT;
2606 case EL_QUICKSAND_EMPTY: return GFX_MORAST_LEER;
2607 case EL_QUICKSAND_FULL: return GFX_MORAST_VOLL;
2608 case EL_QUICKSAND_EMPTYING: return GFX_MORAST_LEER;
2609 case EL_AMOEBA_DROP: return GFX_TROPFEN;
2610 case EL_BOMB: return GFX_BOMBE;
2611 case EL_MAGIC_WALL: return GFX_MAGIC_WALL_OFF;
2612 case EL_MAGIC_WALL_ACTIVE: return GFX_MAGIC_WALL_EMPTY;
2613 case EL_MAGIC_WALL_EMPTYING: return GFX_MAGIC_WALL_EMPTY;
2614 case EL_MAGIC_WALL_FULL: return GFX_MAGIC_WALL_FULL;
2615 case EL_MAGIC_WALL_DEAD: return GFX_MAGIC_WALL_DEAD;
2616 case EL_ACID: return GFX_SALZSAEURE;
2617 case EL_AMOEBA_DEAD: return GFX_AMOEBE_TOT;
2618 case EL_AMOEBA_WET: return GFX_AMOEBE_NASS;
2619 case EL_AMOEBA_DRY: return GFX_AMOEBE_NORM;
2620 case EL_AMOEBA_FULL: return GFX_AMOEBE_VOLL;
2621 case EL_BD_AMOEBA: return GFX_AMOEBE_BD;
2622 case EL_AMOEBA_TO_DIAMOND: return GFX_AMOEBA2DIAM;
2623 case EL_AMOEBA_DRIPPING: return GFX_AMOEBE_NASS;
2624 case EL_NUT: return GFX_KOKOSNUSS;
2625 case EL_GAMEOFLIFE: return GFX_LIFE;
2626 case EL_BIOMAZE: return GFX_LIFE_ASYNC;
2627 case EL_DYNAMITE_ACTIVE: return GFX_DYNAMIT;
2628 case EL_STONEBLOCK: return GFX_BADEWANNE;
2629 case EL_ACIDPOOL_TOPLEFT: return GFX_BADEWANNE1;
2630 case EL_ACIDPOOL_TOPRIGHT: return GFX_BADEWANNE2;
2631 case EL_ACIDPOOL_BOTTOMLEFT: return GFX_BADEWANNE3;
2632 case EL_ACIDPOOL_BOTTOM: return GFX_BADEWANNE4;
2633 case EL_ACIDPOOL_BOTTOMRIGHT: return GFX_BADEWANNE5;
2634 case EL_ROBOT_WHEEL: return GFX_ABLENK_AUS;
2635 case EL_ROBOT_WHEEL_ACTIVE: return GFX_ABLENK_EIN;
2636 case EL_KEY1: return GFX_SCHLUESSEL1;
2637 case EL_KEY2: return GFX_SCHLUESSEL2;
2638 case EL_KEY3: return GFX_SCHLUESSEL3;
2639 case EL_KEY4: return GFX_SCHLUESSEL4;
2640 case EL_GATE1: return GFX_PFORTE1;
2641 case EL_GATE2: return GFX_PFORTE2;
2642 case EL_GATE3: return GFX_PFORTE3;
2643 case EL_GATE4: return GFX_PFORTE4;
2644 case EL_GATE1_GRAY: return GFX_PFORTE1X;
2645 case EL_GATE2_GRAY: return GFX_PFORTE2X;
2646 case EL_GATE3_GRAY: return GFX_PFORTE3X;
2647 case EL_GATE4_GRAY: return GFX_PFORTE4X;
2648 case EL_DYNAMITE: return GFX_DYNAMIT_AUS;
2649 case EL_PACMAN: return GFX_PACMAN;
2650 case EL_PACMAN_RIGHT: return GFX_PACMAN_RIGHT;
2651 case EL_PACMAN_UP: return GFX_PACMAN_UP;
2652 case EL_PACMAN_LEFT: return GFX_PACMAN_LEFT;
2653 case EL_PACMAN_DOWN: return GFX_PACMAN_DOWN;
2654 case EL_INVISIBLE_WALL: return GFX_UNSICHTBAR;
2655 case EL_INVISIBLE_WALL_ACTIVE: return GFX_UNSICHTBAR_ON;
2656 case EL_WALL_EMERALD: return GFX_ERZ_EDEL;
2657 case EL_WALL_DIAMOND: return GFX_ERZ_DIAM;
2658 case EL_LAMP: return GFX_BIRNE_AUS;
2659 case EL_LAMP_ACTIVE: return GFX_BIRNE_EIN;
2660 case EL_TIME_ORB_FULL: return GFX_ZEIT_VOLL;
2661 case EL_TIME_ORB_EMPTY: return GFX_ZEIT_LEER;
2662 case EL_WALL_GROWING: return GFX_MAUER_LEBT;
2663 case EL_WALL_GROWING_X: return GFX_MAUER_X;
2664 case EL_WALL_GROWING_Y: return GFX_MAUER_Y;
2665 case EL_WALL_GROWING_XY: return GFX_MAUER_XY;
2666 case EL_BD_DIAMOND: return GFX_EDELSTEIN_BD;
2667 case EL_EMERALD_YELLOW: return GFX_EDELSTEIN_GELB;
2668 case EL_EMERALD_RED: return GFX_EDELSTEIN_ROT;
2669 case EL_EMERALD_PURPLE: return GFX_EDELSTEIN_LILA;
2670 case EL_WALL_BD_DIAMOND: return GFX_ERZ_EDEL_BD;
2671 case EL_WALL_EMERALD_YELLOW: return GFX_ERZ_EDEL_GELB;
2672 case EL_WALL_EMERALD_RED: return GFX_ERZ_EDEL_ROT;
2673 case EL_WALL_EMERALD_PURPLE: return GFX_ERZ_EDEL_LILA;
2674 case EL_DARK_YAMYAM: return GFX_MAMPFER2;
2675 case EL_BD_MAGIC_WALL: return GFX_MAGIC_WALL_BD_OFF;
2676 case EL_BD_MAGIC_WALL_ACTIVE: return GFX_MAGIC_WALL_BD_EMPTY;
2677 case EL_BD_MAGIC_WALL_EMPTYING: return GFX_MAGIC_WALL_BD_EMPTY;
2678 case EL_BD_MAGIC_WALL_FULL: return GFX_MAGIC_WALL_BD_FULL;
2679 case EL_BD_MAGIC_WALL_DEAD: return GFX_MAGIC_WALL_BD_DEAD;
2680 case EL_DYNABOMB_PLAYER1_ACTIVE: return GFX_DYNABOMB;
2681 case EL_DYNABOMB_PLAYER2_ACTIVE: return GFX_DYNABOMB;
2682 case EL_DYNABOMB_PLAYER3_ACTIVE: return GFX_DYNABOMB;
2683 case EL_DYNABOMB_PLAYER4_ACTIVE: return GFX_DYNABOMB;
2684 case EL_DYNABOMB_NR: return GFX_DYNABOMB_NR;
2685 case EL_DYNABOMB_SZ: return GFX_DYNABOMB_SZ;
2686 case EL_DYNABOMB_XL: return GFX_DYNABOMB_XL;
2687 case EL_SOKOBAN_OBJECT: return GFX_SOKOBAN_OBJEKT;
2688 case EL_SOKOBAN_FIELD_EMPTY: return GFX_SOKOBAN_FELD_LEER;
2689 case EL_SOKOBAN_FIELD_FULL: return GFX_SOKOBAN_FELD_VOLL;
2690 case EL_MOLE: return GFX_MOLE;
2691 case EL_PENGUIN: return GFX_PINGUIN;
2692 case EL_PIG: return GFX_SCHWEIN;
2693 case EL_DRAGON: return GFX_DRACHE;
2694 case EL_SATELLITE: return GFX_SONDE;
2695 case EL_ARROW_BLUE_LEFT: return GFX_PFEIL_LEFT;
2696 case EL_ARROW_BLUE_RIGHT: return GFX_PFEIL_RIGHT;
2697 case EL_ARROW_BLUE_UP: return GFX_PFEIL_UP;
2698 case EL_ARROW_BLUE_DOWN: return GFX_PFEIL_DOWN;
2699 case EL_SPEED_PILL: return GFX_SPEED_PILL;
2700 case EL_SP_TERMINAL_ACTIVE: return GFX_SP_TERMINAL;
2701 case EL_SP_BUGGY_BASE_ACTIVE: return GFX_SP_BUG_ACTIVE;
2702 case EL_SP_ZONK: return GFX_SP_ZONK;
2703 /* ^^^^^^^^^^ non-standard position in supaplex graphic set! */
2704 case EL_INVISIBLE_STEELWALL: return GFX_INVISIBLE_STEEL;
2705 case EL_INVISIBLE_STEELWALL_ACTIVE: return GFX_INVISIBLE_STEEL_ON;
2706 case EL_BLACK_ORB: return GFX_BLACK_ORB;
2707 case EL_EM_GATE1: return GFX_EM_GATE_1;
2708 case EL_EM_GATE2: return GFX_EM_GATE_2;
2709 case EL_EM_GATE3: return GFX_EM_GATE_3;
2710 case EL_EM_GATE4: return GFX_EM_GATE_4;
2711 case EL_EM_GATE1_GRAY: return GFX_EM_GATE_1X;
2712 case EL_EM_GATE2_GRAY: return GFX_EM_GATE_2X;
2713 case EL_EM_GATE3_GRAY: return GFX_EM_GATE_3X;
2714 case EL_EM_GATE4_GRAY: return GFX_EM_GATE_4X;
2715 case EL_EM_KEY1_FILE: return GFX_EM_KEY_1;
2716 case EL_EM_KEY2_FILE: return GFX_EM_KEY_2;
2717 case EL_EM_KEY3_FILE: return GFX_EM_KEY_3;
2718 case EL_EM_KEY4_FILE: return GFX_EM_KEY_4;
2719 case EL_EM_KEY1: return GFX_EM_KEY_1;
2720 case EL_EM_KEY2: return GFX_EM_KEY_2;
2721 case EL_EM_KEY3: return GFX_EM_KEY_3;
2722 case EL_EM_KEY4: return GFX_EM_KEY_4;
2723 case EL_PEARL: return GFX_PEARL;
2724 case EL_CRYSTAL: return GFX_CRYSTAL;
2725 case EL_WALL_PEARL: return GFX_WALL_PEARL;
2726 case EL_WALL_CRYSTAL: return GFX_WALL_CRYSTAL;
2727 case EL_DOOR_WHITE: return GFX_DOOR_WHITE;
2728 case EL_DOOR_WHITE_GRAY: return GFX_DOOR_WHITE_GRAY;
2729 case EL_KEY_WHITE: return GFX_KEY_WHITE;
2730 case EL_SHIELD_NORMAL: return GFX_SHIELD_PASSIVE;
2731 case EL_SHIELD_DEADLY: return GFX_SHIELD_ACTIVE;
2732 case EL_EXTRA_TIME: return GFX_EXTRA_TIME;
2733 case EL_SWITCHGATE_OPEN: return GFX_SWITCHGATE_OPEN;
2734 case EL_SWITCHGATE_CLOSED: return GFX_SWITCHGATE_CLOSED;
2735 case EL_SWITCHGATE_SWITCH_UP: return GFX_SWITCHGATE_SWITCH_1;
2736 case EL_SWITCHGATE_SWITCH_DOWN: return GFX_SWITCHGATE_SWITCH_2;
2737 case EL_CONVEYOR_BELT1_LEFT: return GFX_BELT1_LEFT;
2738 case EL_CONVEYOR_BELT1_MIDDLE: return GFX_BELT1_MIDDLE;
2739 case EL_CONVEYOR_BELT1_RIGHT: return GFX_BELT1_RIGHT;
2740 case EL_CONVEYOR_BELT1_LEFT_ACTIVE: return GFX_BELT1_LEFT;
2741 case EL_CONVEYOR_BELT1_MIDDLE_ACTIVE:return GFX_BELT1_MIDDLE;
2742 case EL_CONVEYOR_BELT1_RIGHT_ACTIVE:return GFX_BELT1_RIGHT;
2743 case EL_CONVEYOR_BELT1_SWITCH_LEFT: return GFX_BELT1_SWITCH_LEFT;
2744 case EL_CONVEYOR_BELT1_SWITCH_MIDDLE:return GFX_BELT1_SWITCH_MIDDLE;
2745 case EL_CONVEYOR_BELT1_SWITCH_RIGHT:return GFX_BELT1_SWITCH_RIGHT;
2746 case EL_CONVEYOR_BELT2_LEFT: return GFX_BELT2_LEFT;
2747 case EL_CONVEYOR_BELT2_MIDDLE: return GFX_BELT2_MIDDLE;
2748 case EL_CONVEYOR_BELT2_RIGHT: return GFX_BELT2_RIGHT;
2749 case EL_CONVEYOR_BELT2_LEFT_ACTIVE: return GFX_BELT2_LEFT;
2750 case EL_CONVEYOR_BELT2_MIDDLE_ACTIVE:return GFX_BELT2_MIDDLE;
2751 case EL_CONVEYOR_BELT2_RIGHT_ACTIVE:return GFX_BELT2_RIGHT;
2752 case EL_CONVEYOR_BELT2_SWITCH_LEFT: return GFX_BELT2_SWITCH_LEFT;
2753 case EL_CONVEYOR_BELT2_SWITCH_MIDDLE:return GFX_BELT2_SWITCH_MIDDLE;
2754 case EL_CONVEYOR_BELT2_SWITCH_RIGHT:return GFX_BELT2_SWITCH_RIGHT;
2755 case EL_CONVEYOR_BELT3_LEFT: return GFX_BELT3_LEFT;
2756 case EL_CONVEYOR_BELT3_MIDDLE: return GFX_BELT3_MIDDLE;
2757 case EL_CONVEYOR_BELT3_RIGHT: return GFX_BELT3_RIGHT;
2758 case EL_CONVEYOR_BELT3_LEFT_ACTIVE: return GFX_BELT3_LEFT;
2759 case EL_CONVEYOR_BELT3_MIDDLE_ACTIVE:return GFX_BELT3_MIDDLE;
2760 case EL_CONVEYOR_BELT3_RIGHT_ACTIVE:return GFX_BELT3_RIGHT;
2761 case EL_CONVEYOR_BELT3_SWITCH_LEFT: return GFX_BELT3_SWITCH_LEFT;
2762 case EL_CONVEYOR_BELT3_SWITCH_MIDDLE:return GFX_BELT3_SWITCH_MIDDLE;
2763 case EL_CONVEYOR_BELT3_SWITCH_RIGHT:return GFX_BELT3_SWITCH_RIGHT;
2764 case EL_CONVEYOR_BELT4_LEFT: return GFX_BELT4_LEFT;
2765 case EL_CONVEYOR_BELT4_MIDDLE: return GFX_BELT4_MIDDLE;
2766 case EL_CONVEYOR_BELT4_RIGHT: return GFX_BELT4_RIGHT;
2767 case EL_CONVEYOR_BELT4_LEFT_ACTIVE: return GFX_BELT4_LEFT;
2768 case EL_CONVEYOR_BELT4_MIDDLE_ACTIVE:return GFX_BELT4_MIDDLE;
2769 case EL_CONVEYOR_BELT4_RIGHT_ACTIVE:return GFX_BELT4_RIGHT;
2770 case EL_CONVEYOR_BELT4_SWITCH_LEFT: return GFX_BELT4_SWITCH_LEFT;
2771 case EL_CONVEYOR_BELT4_SWITCH_MIDDLE:return GFX_BELT4_SWITCH_MIDDLE;
2772 case EL_CONVEYOR_BELT4_SWITCH_RIGHT:return GFX_BELT4_SWITCH_RIGHT;
2773 case EL_LANDMINE: return GFX_LANDMINE;
2774 case EL_ENVELOPE: return GFX_ENVELOPE;
2775 case EL_LIGHT_SWITCH: return GFX_LIGHT_SWITCH_OFF;
2776 case EL_LIGHT_SWITCH_ACTIVE: return GFX_LIGHT_SWITCH_ON;
2777 case EL_SIGN_EXCLAMATION: return GFX_SIGN_EXCLAMATION;
2778 case EL_SIGN_RADIOACTIVITY: return GFX_SIGN_RADIOACTIVITY;
2779 case EL_SIGN_STOP: return GFX_SIGN_STOP;
2780 case EL_SIGN_WHEELCHAIR: return GFX_SIGN_WHEELCHAIR;
2781 case EL_SIGN_PARKING: return GFX_SIGN_PARKING;
2782 case EL_SIGN_ONEWAY: return GFX_SIGN_ONEWAY;
2783 case EL_SIGN_HEART: return GFX_SIGN_HEART;
2784 case EL_SIGN_TRIANGLE: return GFX_SIGN_TRIANGLE;
2785 case EL_SIGN_ROUND: return GFX_SIGN_ROUND;
2786 case EL_SIGN_EXIT: return GFX_SIGN_EXIT;
2787 case EL_SIGN_YINYANG: return GFX_SIGN_YINYANG;
2788 case EL_SIGN_OTHER: return GFX_SIGN_OTHER;
2789 case EL_MOLE_LEFT: return GFX_MOLE_LEFT;
2790 case EL_MOLE_RIGHT: return GFX_MOLE_RIGHT;
2791 case EL_MOLE_UP: return GFX_MOLE_UP;
2792 case EL_MOLE_DOWN: return GFX_MOLE_DOWN;
2793 case EL_STEELWALL_SLANTED: return GFX_STEEL_SLANTED;
2794 case EL_INVISIBLE_SAND: return GFX_SAND_INVISIBLE;
2795 case EL_INVISIBLE_SAND_ACTIVE: return GFX_SAND_INVISIBLE_ON;
2796 case EL_DX_UNKNOWN_15: return GFX_DX_UNKNOWN_15;
2797 case EL_DX_UNKNOWN_42: return GFX_DX_UNKNOWN_42;
2798 case EL_TIMEGATE_OPEN: return GFX_TIMEGATE_OPEN;
2799 case EL_TIMEGATE_CLOSED: return GFX_TIMEGATE_CLOSED;
2800 case EL_TIMEGATE_SWITCH_ACTIVE: return GFX_TIMEGATE_SWITCH;
2801 case EL_TIMEGATE_SWITCH: return GFX_TIMEGATE_SWITCH;
2802 case EL_BALLOON: return GFX_BALLOON;
2803 case EL_BALLOON_SEND_LEFT: return GFX_BALLOON_SEND_LEFT;
2804 case EL_BALLOON_SEND_RIGHT: return GFX_BALLOON_SEND_RIGHT;
2805 case EL_BALLOON_SEND_UP: return GFX_BALLOON_SEND_UP;
2806 case EL_BALLOON_SEND_DOWN: return GFX_BALLOON_SEND_DOWN;
2807 case EL_BALLOON_SEND_ANY_DIRECTION: return GFX_BALLOON_SEND_ANY;
2808 case EL_EMC_STEELWALL1: return GFX_EMC_STEEL_WALL_1;
2809 case EL_EMC_STEELWALL2: return GFX_EMC_STEEL_WALL_2;
2810 case EL_EMC_STEELWALL3: return GFX_EMC_STEEL_WALL_3;
2811 case EL_EMC_STEELWALL4: return GFX_EMC_STEEL_WALL_4;
2812 case EL_EMC_WALL_PILLAR_UPPER: return GFX_EMC_WALL_1;
2813 case EL_EMC_WALL_PILLAR_MIDDLE: return GFX_EMC_WALL_2;
2814 case EL_EMC_WALL_PILLAR_LOWER: return GFX_EMC_WALL_3;
2815 case EL_EMC_WALL4: return GFX_EMC_WALL_4;
2816 case EL_EMC_WALL5: return GFX_EMC_WALL_5;
2817 case EL_EMC_WALL6: return GFX_EMC_WALL_6;
2818 case EL_EMC_WALL7: return GFX_EMC_WALL_7;
2819 case EL_EMC_WALL8: return GFX_EMC_WALL_8;
2820 case EL_TUBE_ALL: return GFX_TUBE_CROSS;
2821 case EL_TUBE_VERTICAL: return GFX_TUBE_VERTICAL;
2822 case EL_TUBE_HORIZONTAL: return GFX_TUBE_HORIZONTAL;
2823 case EL_TUBE_VERTICAL_LEFT: return GFX_TUBE_VERT_LEFT;
2824 case EL_TUBE_VERTICAL_RIGHT: return GFX_TUBE_VERT_RIGHT;
2825 case EL_TUBE_HORIZONTAL_UP: return GFX_TUBE_HORIZ_UP;
2826 case EL_TUBE_HORIZONTAL_DOWN: return GFX_TUBE_HORIZ_DOWN;
2827 case EL_TUBE_LEFT_UP: return GFX_TUBE_LEFT_UP;
2828 case EL_TUBE_LEFT_DOWN: return GFX_TUBE_LEFT_DOWN;
2829 case EL_TUBE_RIGHT_UP: return GFX_TUBE_RIGHT_UP;
2830 case EL_TUBE_RIGHT_DOWN: return GFX_TUBE_RIGHT_DOWN;
2831 case EL_SPRING: return GFX_SPRING;
2832 case EL_TRAP: return GFX_TRAP_INACTIVE;
2833 case EL_TRAP_ACTIVE: return GFX_TRAP_ACTIVE;
2834 case EL_BD_WALL: return GFX_BD_WALL;
2835 case EL_BD_ROCK: return GFX_BD_ROCK;
2836 case EL_DX_SUPABOMB: return GFX_DX_SUPABOMB;
2837 case EL_SP_MURPHY_CLONE: return GFX_SP_MURPHY_CLONE;
2841 if (IS_CHAR(element))
2842 return GFX_CHAR_START + (element - EL_CHAR_START);
2843 else if (element >= EL_SP_START && element <= EL_SP_END)
2845 int nr_element = element - EL_SP_START;
2846 int gfx_per_line = 8;
2848 (nr_element / gfx_per_line) * SP_PER_LINE +
2849 (nr_element % gfx_per_line);
2851 return GFX_START_ROCKSSP + nr_graphic;
2859 int el2gfx(int element)
2862 int graphic_OLD = el2gfx_OLD(element);
2867 int graphic_NEW = element_info[element].graphic[GFX_ACTION_DEFAULT];
2870 int graphic_OLD = el2gfx_OLD(element);
2872 if (element >= MAX_ELEMENTS)
2874 Error(ERR_WARN, "el2gfx: element == %d >= MAX_ELEMENTS", element);
2877 if (graphic_NEW != graphic_OLD)
2879 Error(ERR_WARN, "el2gfx: graphic_NEW (%d) != graphic_OLD (%d)",
2880 graphic_NEW, graphic_OLD);
2888 int el2img(int element)
2890 int graphic = element_info[element].graphic[GFX_ACTION_DEFAULT];
2894 Error(ERR_WARN, "element %d -> graphic %d -- probably crashing now...",
2901 int el_dir2img(int element, int direction)
2903 return el_dir_act2img(element, direction, GFX_ACTION_DEFAULT);
2906 int el_dir_act2img(int element, int direction, int action)
2908 action = graphics_action_mapping[action];
2909 direction = MV_DIR_BIT(direction);
2911 return element_info[element].direction_graphic[action][direction];