1 /***********************************************************
2 * Rocks'n'Diamonds -- McDuffin Strikes Back! *
3 *----------------------------------------------------------*
4 * (c) 1995-98 Artsoft Entertainment *
8 * phone: ++49 +521 290471 *
9 * email: aeglos@valinor.owl.de *
10 *----------------------------------------------------------*
12 ***********************************************************/
17 #include <machine/joystick.h>
31 extern boolean wait_for_vsync;
34 /* tool button identifiers */
35 #define TOOL_CTRL_ID_YES 0
36 #define TOOL_CTRL_ID_NO 1
37 #define TOOL_CTRL_ID_CONFIRM 2
38 #define TOOL_CTRL_ID_PLAYER_1 3
39 #define TOOL_CTRL_ID_PLAYER_2 4
40 #define TOOL_CTRL_ID_PLAYER_3 5
41 #define TOOL_CTRL_ID_PLAYER_4 6
43 #define NUM_TOOL_BUTTONS 7
45 /* forward declaration for internal use */
46 static int getGraphicAnimationPhase(int, int, int);
47 static void DrawGraphicAnimationShiftedThruMask(int, int, int, int, int,
49 static void UnmapToolButtons();
50 static void HandleToolButtons(struct GadgetInfo *);
52 static struct GadgetInfo *tool_gadget[NUM_TOOL_BUTTONS];
53 static int request_gadget_id = -1;
55 void SetDrawtoField(int mode)
57 if (mode == DRAW_BUFFERED && setup.soft_scrolling)
68 drawto_field = fieldbuffer;
70 else /* DRAW_DIRECT, DRAW_BACKBUFFER */
81 drawto_field = (mode == DRAW_DIRECT ? window : backbuffer);
88 Drawable buffer = (drawto_field == window ? backbuffer : drawto_field);
90 if (setup.direct_draw && game_status == PLAYING)
91 redraw_mask &= ~REDRAW_MAIN;
93 if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD)
94 redraw_mask |= REDRAW_FIELD;
96 if (redraw_mask & REDRAW_FIELD)
97 redraw_mask &= ~REDRAW_TILES;
102 /* synchronize X11 graphics at this point; if we would synchronize the
103 display immediately after the buffer switching (after the XFlush),
104 this could mean that we have to wait for the graphics to complete,
105 although we could go on doing calculations for the next frame */
107 XSync(display, FALSE);
109 if (redraw_mask & REDRAW_ALL)
111 XCopyArea(display, backbuffer, window, gc,
112 0, 0, WIN_XSIZE, WIN_YSIZE,
117 if (redraw_mask & REDRAW_FIELD)
119 if (game_status != PLAYING || redraw_mask & REDRAW_FROM_BACKBUFFER)
121 XCopyArea(display, backbuffer, window, gc,
122 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
127 int fx = FX, fy = FY;
129 if (setup.soft_scrolling)
131 fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
132 fy += (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
135 if (setup.soft_scrolling ||
136 ABS(ScreenMovPos) + ScrollStepSize == TILEX ||
137 ABS(ScreenMovPos) == ScrollStepSize ||
138 redraw_tiles > REDRAWTILES_THRESHOLD)
140 XCopyArea(display, buffer, window, gc, fx, fy, SXSIZE, SYSIZE, SX, SY);
144 printf("redrawing all (ScreenGfxPos == %d) because %s\n",
146 (setup.soft_scrolling ?
147 "setup.soft_scrolling" :
148 ABS(ScreenGfxPos) + ScrollStepSize == TILEX ?
149 "ABS(ScreenGfxPos) + ScrollStepSize == TILEX" :
150 ABS(ScreenGfxPos) == ScrollStepSize ?
151 "ABS(ScreenGfxPos) == ScrollStepSize" :
152 "redraw_tiles > REDRAWTILES_THRESHOLD"));
157 redraw_mask &= ~REDRAW_MAIN;
160 if (redraw_mask & REDRAW_DOORS)
162 if (redraw_mask & REDRAW_DOOR_1)
163 XCopyArea(display, backbuffer, window, gc,
164 DX, DY, DXSIZE, DYSIZE,
166 if (redraw_mask & REDRAW_DOOR_2)
168 if ((redraw_mask & REDRAW_DOOR_2) == REDRAW_DOOR_2)
169 XCopyArea(display,backbuffer,window,gc,
170 VX,VY, VXSIZE,VYSIZE,
174 if (redraw_mask & REDRAW_VIDEO_1)
175 XCopyArea(display,backbuffer,window,gc,
176 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS,
177 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
178 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS);
179 if (redraw_mask & REDRAW_VIDEO_2)
180 XCopyArea(display,backbuffer,window,gc,
181 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS,
182 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
183 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS);
184 if (redraw_mask & REDRAW_VIDEO_3)
185 XCopyArea(display,backbuffer,window,gc,
186 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS,
187 VIDEO_CONTROL_XSIZE,VIDEO_CONTROL_YSIZE,
188 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS);
191 if (redraw_mask & REDRAW_DOOR_3)
192 XCopyArea(display, backbuffer, window, gc,
193 EX, EY, EXSIZE, EYSIZE,
195 redraw_mask &= ~REDRAW_DOORS;
198 if (redraw_mask & REDRAW_MICROLEVEL)
200 XCopyArea(display,backbuffer,window,gc,
201 MICROLEV_XPOS, MICROLEV_YPOS, MICROLEV_XSIZE, MICROLEV_YSIZE,
202 MICROLEV_XPOS, MICROLEV_YPOS);
203 XCopyArea(display,backbuffer,window,gc,
204 SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE,
205 SX, MICROLABEL_YPOS);
206 redraw_mask &= ~REDRAW_MICROLEVEL;
209 if (redraw_mask & REDRAW_TILES)
211 for(x=0; x<SCR_FIELDX; x++)
212 for(y=0; y<SCR_FIELDY; y++)
213 if (redraw[redraw_x1 + x][redraw_y1 + y])
214 XCopyArea(display, buffer, window, gc,
215 FX + x * TILEX, FX + y * TILEY, TILEX, TILEY,
216 SX + x * TILEX, SY + y * TILEY);
221 for(x=0; x<MAX_BUF_XSIZE; x++)
222 for(y=0; y<MAX_BUF_YSIZE; y++)
231 long fading_delay = 300;
233 if (setup.fading && (redraw_mask & REDRAW_FIELD))
240 XFillRectangle(display,window,gc,
241 REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
244 for(i=0;i<2*FULL_SYSIZE;i++)
246 for(y=0;y<FULL_SYSIZE;y++)
248 XCopyArea(display,backbuffer,window,gc,
249 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
257 for(i=1;i<FULL_SYSIZE;i+=2)
258 XCopyArea(display,backbuffer,window,gc,
259 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
265 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,0);
266 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
267 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
271 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,-1);
272 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
273 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
277 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,-1);
278 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
279 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
283 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,0);
284 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
285 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
289 redraw_mask &= ~REDRAW_MAIN;
298 XFillRectangle(display, backbuffer, gc,
299 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
301 if (setup.soft_scrolling && game_status == PLAYING)
303 XFillRectangle(display, fieldbuffer, gc, 0, 0, FXSIZE, FYSIZE);
304 SetDrawtoField(DRAW_BUFFERED);
307 SetDrawtoField(DRAW_BACKBUFFER);
309 if (setup.direct_draw && game_status == PLAYING)
311 XFillRectangle(display, window, gc,
312 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
313 SetDrawtoField(DRAW_DIRECT);
316 redraw_mask |= REDRAW_FIELD;
319 int getFontWidth(int font_size, int font_type)
321 return (font_size == FS_BIG ? FONT1_XSIZE :
322 font_size == FS_MEDIUM ? FONT6_XSIZE :
323 font_type == FC_SPECIAL1 ? FONT3_XSIZE :
324 font_type == FC_SPECIAL2 ? FONT4_XSIZE :
325 font_type == FC_SPECIAL3 ? FONT5_XSIZE :
329 int getFontHeight(int font_size, int font_type)
331 return (font_size == FS_BIG ? FONT1_YSIZE :
332 font_size == FS_MEDIUM ? FONT6_YSIZE :
333 font_type == FC_SPECIAL1 ? FONT3_YSIZE :
334 font_type == FC_SPECIAL2 ? FONT4_YSIZE :
335 font_type == FC_SPECIAL3 ? FONT5_YSIZE :
339 void DrawInitText(char *text, int ypos, int color)
341 #ifdef USE_SDL_LIBRARY
342 if (sdl_window && sdl_pix[PIX_SMALLFONT])
344 SDLFillRectangle(sdl_window, 0, ypos, WIN_XSIZE, FONT2_YSIZE, 0x000000);
345 DrawTextExt(window, gc, (WIN_XSIZE - strlen(text) * FONT2_XSIZE)/2,
346 ypos,text,FS_SMALL,color);
347 SDL_Flip(sdl_window);
350 if (display && window && pix[PIX_SMALLFONT])
352 XFillRectangle(display, window, gc, 0, ypos, WIN_XSIZE, FONT2_YSIZE);
353 DrawTextExt(window, gc, (WIN_XSIZE - strlen(text) * FONT2_XSIZE)/2,
354 ypos,text,FS_SMALL,color);
360 void DrawTextFCentered(int y, int font_type, char *format, ...)
362 char buffer[FULL_SXSIZE / FONT5_XSIZE + 10];
363 int font_width = getFontWidth(FS_SMALL, font_type);
366 va_start(ap, format);
367 vsprintf(buffer, format, ap);
370 DrawText(SX + (SXSIZE - strlen(buffer) * font_width) / 2, SY + y,
371 buffer, FS_SMALL, font_type);
374 void DrawTextF(int x, int y, int font_type, char *format, ...)
376 char buffer[FULL_SXSIZE / FONT5_XSIZE + 10];
379 va_start(ap, format);
380 vsprintf(buffer, format, ap);
383 DrawText(SX + x, SY + y, buffer, FS_SMALL, font_type);
386 void DrawText(int x, int y, char *text, int font_size, int font_type)
388 DrawTextExt(drawto, gc, x, y, text, font_size, font_type);
391 redraw_mask |= REDRAW_FIELD;
393 redraw_mask |= REDRAW_DOOR_1;
396 void DrawTextExt(Drawable d, GC gc, int x, int y,
397 char *text, int font_size, int font_type)
399 int font_width, font_height, font_start;
401 boolean print_inverse = FALSE;
403 if (font_size != FS_SMALL && font_size != FS_BIG && font_size != FS_MEDIUM)
404 font_size = FS_SMALL;
405 if (font_type < FC_RED || font_type > FC_SPECIAL3)
408 font_width = getFontWidth(font_size, font_type);
409 font_height = getFontHeight(font_size, font_type);
411 font_pixmap = (font_size == FS_BIG ? PIX_BIGFONT :
412 font_size == FS_MEDIUM ? PIX_MEDIUMFONT :
414 font_start = (font_type * (font_size == FS_BIG ? FONT1_YSIZE :
415 font_size == FS_MEDIUM ? FONT6_YSIZE :
417 FONT_LINES_PER_FONT);
419 if (font_type == FC_SPECIAL3)
420 font_start += (FONT4_YSIZE - FONT2_YSIZE) * FONT_LINES_PER_FONT;
426 if (c == '~' && font_size == FS_SMALL)
428 print_inverse = TRUE;
432 if (c >= 'a' && c <= 'z')
434 else if (c == 'ä' || c == 'Ä')
436 else if (c == 'ö' || c == 'Ö')
438 else if (c == 'ü' || c == 'Ü')
441 if (c >= 32 && c <= 95)
443 int src_x = ((c - 32) % FONT_CHARS_PER_LINE) * font_width;
444 int src_y = ((c - 32) / FONT_CHARS_PER_LINE) * font_height + font_start;
445 int dest_x = x, dest_y = y;
449 XCopyArea(display, pix[font_pixmap], d, gc,
450 FONT_CHARS_PER_LINE * font_width,
451 3 * font_height + font_start,
452 font_width, font_height, x, y);
454 XSetClipOrigin(display, clip_gc[font_pixmap],
455 dest_x - src_x, dest_y - src_y);
456 XCopyArea(display, pix[font_pixmap], d, clip_gc[font_pixmap],
457 0, 0, font_width, font_height, dest_x, dest_y);
461 #ifdef USE_SDL_LIBRARY
462 SDLCopyArea(sdl_pix[font_pixmap], sdl_window,
463 src_x, src_y, font_width, font_height, dest_x, dest_y);
465 XCopyArea(display, pix[font_pixmap], d, gc,
466 src_x, src_y, font_width, font_height, dest_x, dest_y);
475 void DrawAllPlayers()
479 for(i=0; i<MAX_PLAYERS; i++)
480 if (stored_player[i].active)
481 DrawPlayer(&stored_player[i]);
484 void DrawPlayerField(int x, int y)
486 if (!IS_PLAYER(x, y))
489 DrawPlayer(PLAYERINFO(x, y));
492 void DrawPlayer(struct PlayerInfo *player)
494 int jx = player->jx, jy = player->jy;
495 int last_jx = player->last_jx, last_jy = player->last_jy;
496 int next_jx = jx + (jx - last_jx), next_jy = jy + (jy - last_jy);
497 int sx = SCREENX(jx), sy = SCREENY(jy);
498 int sxx = 0, syy = 0;
499 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
501 boolean player_is_moving = (last_jx != jx || last_jy != jy ? TRUE : FALSE);
503 if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
507 if (!IN_LEV_FIELD(jx,jy))
509 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
510 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
511 printf("DrawPlayerField(): This should never happen!\n");
516 if (element == EL_EXPLODING)
519 /* draw things in the field the player is leaving, if needed */
521 if (player_is_moving)
523 if (Store[last_jx][last_jy] && IS_DRAWABLE(last_element))
525 DrawLevelElement(last_jx, last_jy, Store[last_jx][last_jy]);
526 DrawLevelFieldThruMask(last_jx, last_jy);
528 else if (last_element == EL_DYNAMITE_ACTIVE)
529 DrawDynamite(last_jx, last_jy);
531 DrawLevelField(last_jx, last_jy);
533 if (player->Pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
537 if (Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
538 DrawLevelElement(next_jx, next_jy, EL_SOKOBAN_FELD_LEER);
540 DrawLevelElement(next_jx, next_jy, EL_LEERRAUM);
543 DrawLevelField(next_jx, next_jy);
547 if (!IN_SCR_FIELD(sx, sy))
550 if (setup.direct_draw)
551 SetDrawtoField(DRAW_BUFFERED);
553 /* draw things behind the player, if needed */
556 DrawLevelElement(jx, jy, Store[jx][jy]);
557 else if (!IS_ACTIVE_BOMB(element))
558 DrawLevelField(jx, jy);
560 /* draw player himself */
562 if (game.emulation == EMU_SUPAPLEX)
564 static int last_dir = MV_LEFT;
565 int action = (player->programmed_action ? player->programmed_action :
567 boolean action_moving =
569 ((action & (MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN)) &&
570 !(action & ~(MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN))));
572 graphic = GFX_SP_MURPHY;
576 if (player->MovDir == MV_LEFT)
577 graphic = GFX_MURPHY_PUSH_LEFT;
578 else if (player->MovDir == MV_RIGHT)
579 graphic = GFX_MURPHY_PUSH_RIGHT;
580 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
581 graphic = GFX_MURPHY_PUSH_LEFT;
582 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
583 graphic = GFX_MURPHY_PUSH_RIGHT;
585 else if (player->snapped)
587 if (player->MovDir == MV_LEFT)
588 graphic = GFX_MURPHY_SNAP_LEFT;
589 else if (player->MovDir == MV_RIGHT)
590 graphic = GFX_MURPHY_SNAP_RIGHT;
591 else if (player->MovDir == MV_UP)
592 graphic = GFX_MURPHY_SNAP_UP;
593 else if (player->MovDir == MV_DOWN)
594 graphic = GFX_MURPHY_SNAP_DOWN;
596 else if (action_moving)
598 if (player->MovDir == MV_LEFT)
599 graphic = GFX_MURPHY_GO_LEFT;
600 else if (player->MovDir == MV_RIGHT)
601 graphic = GFX_MURPHY_GO_RIGHT;
602 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
603 graphic = GFX_MURPHY_GO_LEFT;
604 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
605 graphic = GFX_MURPHY_GO_RIGHT;
607 graphic = GFX_MURPHY_GO_LEFT;
609 graphic += getGraphicAnimationPhase(3, 2, ANIM_OSCILLATE);
612 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
613 last_dir = player->MovDir;
617 if (player->MovDir == MV_LEFT)
619 (player->Pushing ? GFX_SPIELER1_PUSH_LEFT : GFX_SPIELER1_LEFT);
620 else if (player->MovDir == MV_RIGHT)
622 (player->Pushing ? GFX_SPIELER1_PUSH_RIGHT : GFX_SPIELER1_RIGHT);
623 else if (player->MovDir == MV_UP)
624 graphic = GFX_SPIELER1_UP;
625 else /* MV_DOWN || MV_NO_MOVING */
626 graphic = GFX_SPIELER1_DOWN;
628 graphic += player->index_nr * 3 * HEROES_PER_LINE;
629 graphic += player->Frame;
634 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
635 sxx = player->GfxPos;
637 syy = player->GfxPos;
640 if (!setup.soft_scrolling && ScreenMovPos)
643 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, NO_CUTTING);
645 if (SHIELD_ON(player))
647 int graphic = (player->shield_active_time_left ? GFX2_SHIELD_ACTIVE :
648 GFX2_SHIELD_PASSIVE);
650 DrawGraphicAnimationShiftedThruMask(sx, sy, sxx, syy, graphic,
651 3, 8, ANIM_OSCILLATE);
654 if (player->Pushing && player->GfxPos)
656 int px = SCREENX(next_jx), py = SCREENY(next_jy);
658 if (element == EL_SOKOBAN_FELD_LEER ||
659 Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
660 DrawGraphicShiftedThruMask(px, py, sxx, syy, GFX_SOKOBAN_OBJEKT,
664 int element = Feld[next_jx][next_jy];
665 int graphic = el2gfx(element);
667 if ((element == EL_FELSBROCKEN ||
668 element == EL_SP_ZONK ||
669 element == EL_BD_ROCK) && sxx)
671 int phase = (player->GfxPos / (TILEX / 4));
673 if (player->MovDir == MV_LEFT)
676 graphic += (phase + 4) % 4;
679 DrawGraphicShifted(px, py, sxx, syy, graphic, NO_CUTTING, NO_MASKING);
683 /* draw things in front of player (active dynamite or dynabombs) */
685 if (IS_ACTIVE_BOMB(element))
687 graphic = el2gfx(element);
689 if (element == EL_DYNAMITE_ACTIVE)
691 if ((phase = (96 - MovDelay[jx][jy]) / 12) > 6)
696 if ((phase = ((96 - MovDelay[jx][jy]) / 6) % 8) > 3)
700 if (game.emulation == EMU_SUPAPLEX)
701 DrawGraphic(sx, sy, GFX_SP_DISK_RED);
703 DrawGraphicThruMask(sx, sy, graphic + phase);
706 if (player_is_moving && last_element == EL_EXPLODING)
708 int phase = Frame[last_jx][last_jy];
712 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy),
713 GFX_EXPLOSION + ((phase - 1) / delay - 1));
716 /* draw elements that stay over the player */
717 /* handle the field the player is leaving ... */
718 if (player_is_moving && IS_OVER_PLAYER(last_element))
719 DrawLevelField(last_jx, last_jy);
720 /* ... and the field the player is entering */
721 if (IS_OVER_PLAYER(element))
722 DrawLevelField(jx, jy);
724 if (setup.direct_draw)
726 int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
727 int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
728 int x_size = TILEX * (1 + ABS(jx - last_jx));
729 int y_size = TILEY * (1 + ABS(jy - last_jy));
731 XCopyArea(display, drawto_field, window, gc,
732 dest_x, dest_y, x_size, y_size, dest_x, dest_y);
733 SetDrawtoField(DRAW_DIRECT);
736 MarkTileDirty(sx,sy);
739 static int getGraphicAnimationPhase(int frames, int delay, int mode)
743 if (mode == ANIM_OSCILLATE)
745 int max_anim_frames = 2 * frames - 2;
746 phase = (FrameCounter % (delay * max_anim_frames)) / delay;
747 phase = (phase < frames ? phase : max_anim_frames - phase);
750 phase = (FrameCounter % (delay * frames)) / delay;
752 if (mode == ANIM_REVERSE)
758 void DrawGraphicAnimationExt(int x, int y, int graphic,
759 int frames, int delay, int mode, int mask_mode)
761 int phase = getGraphicAnimationPhase(frames, delay, mode);
763 if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
765 if (mask_mode == USE_MASKING)
766 DrawGraphicThruMask(SCREENX(x), SCREENY(y), graphic + phase);
768 DrawGraphic(SCREENX(x), SCREENY(y), graphic + phase);
772 void DrawGraphicAnimation(int x, int y, int graphic,
773 int frames, int delay, int mode)
775 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, NO_MASKING);
778 void DrawGraphicAnimationThruMask(int x, int y, int graphic,
779 int frames, int delay, int mode)
781 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, USE_MASKING);
784 static void DrawGraphicAnimationShiftedThruMask(int sx, int sy,
787 int frames, int delay,
790 int phase = getGraphicAnimationPhase(frames, delay, mode);
792 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic + phase, NO_CUTTING);
795 void getGraphicSource(int graphic, int *pixmap_nr, int *x, int *y)
797 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
799 graphic -= GFX_START_ROCKSSCREEN;
800 *pixmap_nr = PIX_BACK;
801 *x = SX + (graphic % GFX_PER_LINE) * TILEX;
802 *y = SY + (graphic / GFX_PER_LINE) * TILEY;
804 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
806 graphic -= GFX_START_ROCKSHEROES;
807 *pixmap_nr = PIX_HEROES;
808 *x = (graphic % HEROES_PER_LINE) * TILEX;
809 *y = (graphic / HEROES_PER_LINE) * TILEY;
811 else if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
813 graphic -= GFX_START_ROCKSSP;
815 *x = (graphic % SP_PER_LINE) * TILEX;
816 *y = (graphic / SP_PER_LINE) * TILEY;
818 else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
820 graphic -= GFX_START_ROCKSDC;
822 *x = (graphic % DC_PER_LINE) * TILEX;
823 *y = (graphic / DC_PER_LINE) * TILEY;
825 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
827 graphic -= GFX_START_ROCKSMORE;
828 *pixmap_nr = PIX_MORE;
829 *x = (graphic % MORE_PER_LINE) * TILEX;
830 *y = (graphic / MORE_PER_LINE) * TILEY;
832 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
834 graphic -= GFX_START_ROCKSFONT;
835 *pixmap_nr = PIX_BIGFONT;
836 *x = (graphic % FONT_CHARS_PER_LINE) * TILEX;
837 *y = ((graphic / FONT_CHARS_PER_LINE) * TILEY +
838 FC_SPECIAL1 * FONT_LINES_PER_FONT * TILEY);
848 void DrawGraphic(int x, int y, int graphic)
851 if (!IN_SCR_FIELD(x,y))
853 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
854 printf("DrawGraphic(): This should never happen!\n");
859 DrawGraphicExt(drawto_field, gc, FX + x*TILEX, FY + y*TILEY, graphic);
863 void DrawGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
868 getGraphicSource(graphic, &pixmap_nr, &src_x, &src_y);
869 XCopyArea(display, pix[pixmap_nr], d, gc,
870 src_x, src_y, TILEX, TILEY, x, y);
873 void DrawGraphicThruMask(int x, int y, int graphic)
876 if (!IN_SCR_FIELD(x,y))
878 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
879 printf("DrawGraphicThruMask(): This should never happen!\n");
884 DrawGraphicThruMaskExt(drawto_field, FX + x*TILEX, FY + y*TILEY, graphic);
888 void DrawGraphicThruMaskExt(Drawable d, int dest_x, int dest_y, int graphic)
896 if (graphic == GFX_LEERRAUM)
899 getGraphicSource(graphic, &pixmap_nr, &src_x, &src_y);
900 src_pixmap = pix[pixmap_nr];
901 drawing_gc = clip_gc[pixmap_nr];
903 if (tile_clipmask[tile] != None)
905 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
906 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
907 XCopyArea(display, src_pixmap, d, tile_clip_gc,
908 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
913 printf("DrawGraphicThruMask(): tile '%d' needs clipping!\n", tile);
916 XSetClipOrigin(display, drawing_gc, dest_x-src_x, dest_y-src_y);
917 XCopyArea(display, src_pixmap, d, drawing_gc,
918 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
922 void DrawMiniGraphic(int x, int y, int graphic)
924 DrawMiniGraphicExt(drawto,gc, SX + x*MINI_TILEX, SY + y*MINI_TILEY, graphic);
925 MarkTileDirty(x/2, y/2);
928 void getMiniGraphicSource(int graphic, Pixmap *pixmap, int *x, int *y)
930 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
932 graphic -= GFX_START_ROCKSSCREEN;
933 *pixmap = pix[PIX_BACK];
934 *x = MINI_GFX_STARTX + (graphic % MINI_GFX_PER_LINE) * MINI_TILEX;
935 *y = MINI_GFX_STARTY + (graphic / MINI_GFX_PER_LINE) * MINI_TILEY;
937 else if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
939 graphic -= GFX_START_ROCKSSP;
940 graphic -= ((graphic / SP_PER_LINE) * SP_PER_LINE) / 2;
941 *pixmap = pix[PIX_SP];
942 *x = MINI_SP_STARTX + (graphic % MINI_SP_PER_LINE) * MINI_TILEX;
943 *y = MINI_SP_STARTY + (graphic / MINI_SP_PER_LINE) * MINI_TILEY;
945 else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
947 graphic -= GFX_START_ROCKSDC;
948 *pixmap = pix[PIX_DC];
949 *x = MINI_DC_STARTX + (graphic % MINI_DC_PER_LINE) * MINI_TILEX;
950 *y = MINI_DC_STARTY + (graphic / MINI_DC_PER_LINE) * MINI_TILEY;
952 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
954 graphic -= GFX_START_ROCKSMORE;
955 *pixmap = pix[PIX_MORE];
956 *x = MINI_MORE_STARTX + (graphic % MINI_MORE_PER_LINE) * MINI_TILEX;
957 *y = MINI_MORE_STARTY + (graphic / MINI_MORE_PER_LINE) * MINI_TILEY;
959 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
961 graphic -= GFX_START_ROCKSFONT;
962 *pixmap = pix[PIX_SMALLFONT];
963 *x = (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE;
964 *y = ((graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE +
965 FC_SPECIAL2 * FONT2_YSIZE * FONT_LINES_PER_FONT);
969 *pixmap = pix[PIX_SP];
975 void DrawMiniGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
980 getMiniGraphicSource(graphic, &pixmap, &src_x, &src_y);
981 XCopyArea(display, pixmap, d, gc,
982 src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
985 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
986 int cut_mode, int mask_mode)
988 int width = TILEX, height = TILEY;
990 int src_x, src_y, dest_x, dest_y;
998 DrawGraphic(x, y, graphic);
1002 if (dx || dy) /* Verschiebung der Grafik? */
1004 if (x < BX1) /* Element kommt von links ins Bild */
1011 else if (x > BX2) /* Element kommt von rechts ins Bild */
1017 else if (x==BX1 && dx < 0) /* Element verläßt links das Bild */
1023 else if (x==BX2 && dx > 0) /* Element verläßt rechts das Bild */
1025 else if (dx) /* allg. Bewegung in x-Richtung */
1026 MarkTileDirty(x + SIGN(dx), y);
1028 if (y < BY1) /* Element kommt von oben ins Bild */
1030 if (cut_mode==CUT_BELOW) /* Element oberhalb des Bildes */
1038 else if (y > BY2) /* Element kommt von unten ins Bild */
1044 else if (y==BY1 && dy < 0) /* Element verläßt oben das Bild */
1050 else if (dy > 0 && cut_mode == CUT_ABOVE)
1052 if (y == BY2) /* Element unterhalb des Bildes */
1058 MarkTileDirty(x, y + 1);
1059 } /* Element verläßt unten das Bild */
1060 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1062 else if (dy) /* allg. Bewegung in y-Richtung */
1063 MarkTileDirty(x, y + SIGN(dy));
1066 getGraphicSource(graphic, &pixmap_nr, &src_x, &src_y);
1067 src_pixmap = pix[pixmap_nr];
1068 drawing_gc = clip_gc[pixmap_nr];
1073 dest_x = FX + x * TILEX + dx;
1074 dest_y = FY + y * TILEY + dy;
1077 if (!IN_SCR_FIELD(x,y))
1079 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1080 printf("DrawGraphicShifted(): This should never happen!\n");
1085 if (mask_mode == USE_MASKING)
1087 if (tile_clipmask[tile] != None)
1089 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
1090 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
1091 XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
1092 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
1097 printf("DrawGraphicShifted(): tile '%d' needs clipping!\n", tile);
1100 XSetClipOrigin(display, drawing_gc, dest_x - src_x, dest_y - src_y);
1101 XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
1102 src_x, src_y, width, height, dest_x, dest_y);
1106 XCopyArea(display, src_pixmap, drawto_field, gc,
1107 src_x, src_y, width, height, dest_x, dest_y);
1112 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
1115 DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, USE_MASKING);
1118 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1119 int cut_mode, int mask_mode)
1121 int ux = LEVELX(x), uy = LEVELY(y);
1122 int graphic = el2gfx(element);
1123 int phase8 = ABS(MovPos[ux][uy]) / (TILEX / 8);
1124 int phase4 = phase8 / 2;
1125 int phase2 = phase8 / 4;
1126 int dir = MovDir[ux][uy];
1128 if (element == EL_PACMAN || element == EL_KAEFER || element == EL_FLIEGER)
1130 graphic += 4 * !phase2;
1134 else if (dir == MV_LEFT)
1136 else if (dir == MV_DOWN)
1139 else if (element == EL_SP_SNIKSNAK)
1142 graphic = GFX_SP_SNIKSNAK_LEFT;
1143 else if (dir == MV_RIGHT)
1144 graphic = GFX_SP_SNIKSNAK_RIGHT;
1145 else if (dir == MV_UP)
1146 graphic = GFX_SP_SNIKSNAK_UP;
1148 graphic = GFX_SP_SNIKSNAK_DOWN;
1150 graphic += (phase8 < 4 ? phase8 : 7 - phase8);
1152 else if (element == EL_SP_ELECTRON)
1154 graphic = GFX2_SP_ELECTRON + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1156 else if (element == EL_MOLE || element == EL_PINGUIN ||
1157 element == EL_SCHWEIN || element == EL_DRACHE)
1160 graphic = (element == EL_MOLE ? GFX_MOLE_LEFT :
1161 element == EL_PINGUIN ? GFX_PINGUIN_LEFT :
1162 element == EL_SCHWEIN ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
1163 else if (dir == MV_RIGHT)
1164 graphic = (element == EL_MOLE ? GFX_MOLE_RIGHT :
1165 element == EL_PINGUIN ? GFX_PINGUIN_RIGHT :
1166 element == EL_SCHWEIN ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
1167 else if (dir == MV_UP)
1168 graphic = (element == EL_MOLE ? GFX_MOLE_UP :
1169 element == EL_PINGUIN ? GFX_PINGUIN_UP :
1170 element == EL_SCHWEIN ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
1172 graphic = (element == EL_MOLE ? GFX_MOLE_DOWN :
1173 element == EL_PINGUIN ? GFX_PINGUIN_DOWN :
1174 element == EL_SCHWEIN ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
1178 else if (element == EL_SONDE)
1180 graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1182 else if (element == EL_SALZSAEURE)
1184 graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_NORMAL);
1186 else if (element == EL_BUTTERFLY || element == EL_FIREFLY)
1190 else if (element == EL_BALLOON)
1194 else if ((element == EL_FELSBROCKEN ||
1195 element == EL_SP_ZONK ||
1196 element == EL_BD_ROCK ||
1197 IS_GEM(element)) && !cut_mode)
1199 if (uy >= lev_fieldy-1 || !IS_BELT(Feld[ux][uy+1]))
1201 if (element == EL_FELSBROCKEN ||
1202 element == EL_SP_ZONK ||
1203 element == EL_BD_ROCK)
1206 graphic += (4 - phase4) % 4;
1207 else if (dir == MV_RIGHT)
1210 graphic += phase2 * 2;
1212 else if (element != EL_SP_INFOTRON)
1216 else if (element == EL_MAGIC_WALL_EMPTY ||
1217 element == EL_MAGIC_WALL_BD_EMPTY ||
1218 element == EL_MAGIC_WALL_FULL ||
1219 element == EL_MAGIC_WALL_BD_FULL)
1221 graphic += 3 + getGraphicAnimationPhase(4, 4, ANIM_REVERSE);
1223 else if (IS_AMOEBOID(element))
1225 graphic = (element == EL_AMOEBE_TOT ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
1226 graphic += (x + 2 * y + 4) % 4;
1228 else if (element == EL_MAUER_LEBT)
1230 boolean links_massiv = FALSE, rechts_massiv = FALSE;
1232 if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
1233 links_massiv = TRUE;
1234 if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
1235 rechts_massiv = TRUE;
1237 if (links_massiv && rechts_massiv)
1238 graphic = GFX_MAUERWERK;
1239 else if (links_massiv)
1240 graphic = GFX_MAUER_R;
1241 else if (rechts_massiv)
1242 graphic = GFX_MAUER_L;
1244 else if ((element == EL_INVISIBLE_STEEL ||
1245 element == EL_UNSICHTBAR ||
1246 element == EL_SAND_INVISIBLE) && game.light_time_left)
1248 graphic = (element == EL_INVISIBLE_STEEL ? GFX_INVISIBLE_STEEL_ON :
1249 element == EL_UNSICHTBAR ? GFX_UNSICHTBAR_ON :
1250 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);
1261 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1262 int cut_mode, int mask_mode)
1264 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1265 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1266 cut_mode, mask_mode);
1269 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1272 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1275 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1278 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1281 void DrawScreenElementThruMask(int x, int y, int element)
1283 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1286 void DrawLevelElementThruMask(int x, int y, int element)
1288 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1291 void DrawLevelFieldThruMask(int x, int y)
1293 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1296 void ErdreichAnbroeckeln(int x, int y)
1298 int i, width, height, cx,cy;
1299 int ux = LEVELX(x), uy = LEVELY(y);
1300 int element, graphic;
1302 static int xy[4][2] =
1310 if (!IN_LEV_FIELD(ux, uy))
1313 element = Feld[ux][uy];
1315 if (element == EL_ERDREICH ||
1316 element == EL_LANDMINE ||
1317 element == EL_TRAP_INACTIVE ||
1318 element == EL_TRAP_ACTIVE)
1320 if (!IN_SCR_FIELD(x, y))
1323 graphic = GFX_ERDENRAND;
1329 uxx = ux + xy[i][0];
1330 uyy = uy + xy[i][1];
1331 if (!IN_LEV_FIELD(uxx, uyy))
1334 element = Feld[uxx][uyy];
1336 if (element == EL_ERDREICH ||
1337 element == EL_LANDMINE ||
1338 element == EL_TRAP_INACTIVE ||
1339 element == EL_TRAP_ACTIVE)
1342 if (i == 1 || i == 2)
1346 cx = (i == 2 ? TILEX - snip : 0);
1354 cy = (i == 3 ? TILEY - snip : 0);
1357 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1358 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1359 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1360 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1363 MarkTileDirty(x, y);
1367 graphic = GFX_ERDENRAND;
1371 int xx, yy, uxx, uyy;
1375 uxx = ux + xy[i][0];
1376 uyy = uy + xy[i][1];
1378 if (!IN_LEV_FIELD(uxx, uyy) ||
1379 (Feld[uxx][uyy] != EL_ERDREICH &&
1380 Feld[uxx][uyy] != EL_LANDMINE &&
1381 Feld[uxx][uyy] != EL_TRAP_INACTIVE &&
1382 Feld[uxx][uyy] != EL_TRAP_ACTIVE) ||
1383 !IN_SCR_FIELD(xx, yy))
1386 if (i == 1 || i == 2)
1390 cx = (i == 1 ? TILEX - snip : 0);
1398 cy = (i==0 ? TILEY-snip : 0);
1401 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1402 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1403 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1404 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1406 MarkTileDirty(xx, yy);
1411 void DrawScreenElement(int x, int y, int element)
1413 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1414 ErdreichAnbroeckeln(x, y);
1417 void DrawLevelElement(int x, int y, int element)
1419 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1420 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1423 void DrawScreenField(int x, int y)
1425 int ux = LEVELX(x), uy = LEVELY(y);
1428 if (!IN_LEV_FIELD(ux, uy))
1430 if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
1431 element = EL_LEERRAUM;
1433 element = BorderElement;
1435 DrawScreenElement(x, y, element);
1439 element = Feld[ux][uy];
1441 if (IS_MOVING(ux, uy))
1443 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1444 boolean cut_mode = NO_CUTTING;
1446 if (Store[ux][uy] == EL_MORAST_LEER ||
1447 Store[ux][uy] == EL_MAGIC_WALL_EMPTY ||
1448 Store[ux][uy] == EL_MAGIC_WALL_BD_EMPTY ||
1449 Store[ux][uy] == EL_AMOEBE_NASS)
1450 cut_mode = CUT_ABOVE;
1451 else if (Store[ux][uy] == EL_MORAST_VOLL ||
1452 Store[ux][uy] == EL_MAGIC_WALL_FULL ||
1453 Store[ux][uy] == EL_MAGIC_WALL_BD_FULL)
1454 cut_mode = CUT_BELOW;
1456 if (cut_mode == CUT_ABOVE)
1457 DrawScreenElementShifted(x, y, 0, 0, Store[ux][uy], NO_CUTTING);
1459 DrawScreenElement(x, y, EL_LEERRAUM);
1462 DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1464 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1466 if (Store[ux][uy] == EL_SALZSAEURE)
1467 DrawLevelElementThruMask(ux, uy + 1, EL_SALZSAEURE);
1469 else if (IS_BLOCKED(ux, uy))
1474 boolean cut_mode = NO_CUTTING;
1476 Blocked2Moving(ux, uy, &oldx, &oldy);
1479 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1480 MovDir[oldx][oldy] == MV_RIGHT);
1482 if (Store[oldx][oldy] == EL_MORAST_LEER ||
1483 Store[oldx][oldy] == EL_MAGIC_WALL_EMPTY ||
1484 Store[oldx][oldy] == EL_MAGIC_WALL_BD_EMPTY ||
1485 Store[oldx][oldy] == EL_AMOEBE_NASS)
1486 cut_mode = CUT_ABOVE;
1488 DrawScreenElement(x, y, EL_LEERRAUM);
1489 element = Feld[oldx][oldy];
1492 DrawScreenElementShifted(sx,sy, MovPos[oldx][oldy],0,element,NO_CUTTING);
1494 DrawScreenElementShifted(sx,sy, 0,MovPos[oldx][oldy],element,cut_mode);
1496 else if (IS_DRAWABLE(element))
1497 DrawScreenElement(x, y, element);
1499 DrawScreenElement(x, y, EL_LEERRAUM);
1502 void DrawLevelField(int x, int y)
1504 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1505 DrawScreenField(SCREENX(x), SCREENY(y));
1506 else if (IS_MOVING(x, y))
1510 Moving2Blocked(x, y, &newx, &newy);
1511 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1512 DrawScreenField(SCREENX(newx), SCREENY(newy));
1514 else if (IS_BLOCKED(x, y))
1518 Blocked2Moving(x, y, &oldx, &oldy);
1519 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1520 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1524 void DrawMiniElement(int x, int y, int element)
1530 DrawMiniGraphic(x, y, -1);
1534 graphic = el2gfx(element);
1535 DrawMiniGraphic(x, y, graphic);
1538 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1540 int x = sx + scroll_x, y = sy + scroll_y;
1542 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1543 DrawMiniElement(sx, sy, EL_LEERRAUM);
1544 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1545 DrawMiniElement(sx, sy, Feld[x][y]);
1548 int steel_type, steel_position;
1551 { GFX_VSTEEL_UPPER_LEFT, GFX_ISTEEL_UPPER_LEFT },
1552 { GFX_VSTEEL_UPPER_RIGHT, GFX_ISTEEL_UPPER_RIGHT },
1553 { GFX_VSTEEL_LOWER_LEFT, GFX_ISTEEL_LOWER_LEFT },
1554 { GFX_VSTEEL_LOWER_RIGHT, GFX_ISTEEL_LOWER_RIGHT },
1555 { GFX_VSTEEL_VERTICAL, GFX_ISTEEL_VERTICAL },
1556 { GFX_VSTEEL_HORIZONTAL, GFX_ISTEEL_HORIZONTAL }
1559 steel_type = (BorderElement == EL_BETON ? 0 : 1);
1560 steel_position = (x == -1 && y == -1 ? 0 :
1561 x == lev_fieldx && y == -1 ? 1 :
1562 x == -1 && y == lev_fieldy ? 2 :
1563 x == lev_fieldx && y == lev_fieldy ? 3 :
1564 x == -1 || x == lev_fieldx ? 4 :
1565 y == -1 || y == lev_fieldy ? 5 : -1);
1567 if (steel_position != -1)
1568 DrawMiniGraphic(sx, sy, border[steel_position][steel_type]);
1572 void DrawMicroElement(int xpos, int ypos, int element)
1576 if (element == EL_LEERRAUM)
1579 graphic = el2gfx(element);
1581 if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
1583 graphic -= GFX_START_ROCKSSP;
1584 graphic -= ((graphic / SP_PER_LINE) * SP_PER_LINE) / 2;
1585 XCopyArea(display, pix[PIX_SP], drawto, gc,
1586 MICRO_SP_STARTX + (graphic % MICRO_SP_PER_LINE) * MICRO_TILEX,
1587 MICRO_SP_STARTY + (graphic / MICRO_SP_PER_LINE) * MICRO_TILEY,
1588 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1590 else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
1592 graphic -= GFX_START_ROCKSDC;
1593 XCopyArea(display, pix[PIX_DC], drawto, gc,
1594 MICRO_DC_STARTX + (graphic % MICRO_DC_PER_LINE) * MICRO_TILEX,
1595 MICRO_DC_STARTY + (graphic / MICRO_DC_PER_LINE) * MICRO_TILEY,
1596 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1598 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
1600 graphic -= GFX_START_ROCKSMORE;
1601 XCopyArea(display, pix[PIX_MORE], drawto, gc,
1602 MICRO_MORE_STARTX + (graphic % MICRO_MORE_PER_LINE) *MICRO_TILEX,
1603 MICRO_MORE_STARTY + (graphic / MICRO_MORE_PER_LINE) *MICRO_TILEY,
1604 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1607 XCopyArea(display, pix[PIX_BACK], drawto, gc,
1608 MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX,
1609 MICRO_GFX_STARTY + (graphic / MICRO_GFX_PER_LINE) * MICRO_TILEY,
1610 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1619 for(x=BX1; x<=BX2; x++)
1620 for(y=BY1; y<=BY2; y++)
1621 DrawScreenField(x, y);
1623 redraw_mask |= REDRAW_FIELD;
1626 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1630 for(x=0; x<size_x; x++)
1631 for(y=0; y<size_y; y++)
1632 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1634 redraw_mask |= REDRAW_FIELD;
1637 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1641 XFillRectangle(display, drawto, gc,
1642 xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
1644 if (lev_fieldx < STD_LEV_FIELDX)
1645 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1646 if (lev_fieldy < STD_LEV_FIELDY)
1647 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1649 xpos += MICRO_TILEX;
1650 ypos += MICRO_TILEY;
1652 for(x=-1; x<=STD_LEV_FIELDX; x++)
1654 for(y=-1; y<=STD_LEV_FIELDY; y++)
1656 int lx = from_x + x, ly = from_y + y;
1658 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1659 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1661 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1)
1662 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1667 redraw_mask |= REDRAW_MICROLEVEL;
1670 #define MICROLABEL_EMPTY 0
1671 #define MICROLABEL_LEVEL_NAME 1
1672 #define MICROLABEL_CREATED_BY 2
1673 #define MICROLABEL_LEVEL_AUTHOR 3
1674 #define MICROLABEL_IMPORTED_FROM 4
1675 #define MICROLABEL_LEVEL_IMPORT_INFO 5
1677 #define MAX_MICROLABEL_SIZE (SXSIZE / FONT4_XSIZE)
1679 static void DrawMicroLevelLabelExt(int mode)
1681 char label_text[MAX_MICROLABEL_SIZE + 1];
1683 XFillRectangle(display, drawto,gc,
1684 SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
1686 strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
1687 mode == MICROLABEL_CREATED_BY ? "created by" :
1688 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
1689 mode == MICROLABEL_IMPORTED_FROM ? "imported from" :
1690 mode == MICROLABEL_LEVEL_IMPORT_INFO ?
1691 leveldir_current->imported_from : ""),
1692 MAX_MICROLABEL_SIZE);
1693 label_text[MAX_MICROLABEL_SIZE] = '\0';
1695 if (strlen(label_text) > 0)
1697 int lxpos = SX + (SXSIZE - strlen(label_text) * FONT4_XSIZE) / 2;
1698 int lypos = MICROLABEL_YPOS;
1700 DrawText(lxpos, lypos, label_text, FS_SMALL, FC_SPECIAL2);
1703 redraw_mask |= REDRAW_MICROLEVEL;
1706 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1708 static unsigned long scroll_delay = 0;
1709 static unsigned long label_delay = 0;
1710 static int from_x, from_y, scroll_direction;
1711 static int label_state, label_counter;
1715 from_x = from_y = 0;
1716 scroll_direction = MV_RIGHT;
1720 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1721 DrawMicroLevelLabelExt(label_state);
1723 /* initialize delay counters */
1724 DelayReached(&scroll_delay, 0);
1725 DelayReached(&label_delay, 0);
1730 /* scroll micro level, if needed */
1731 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1732 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1734 switch (scroll_direction)
1740 scroll_direction = MV_UP;
1744 if (from_x < lev_fieldx - STD_LEV_FIELDX)
1747 scroll_direction = MV_DOWN;
1754 scroll_direction = MV_RIGHT;
1758 if (from_y < lev_fieldy - STD_LEV_FIELDY)
1761 scroll_direction = MV_LEFT;
1768 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1771 /* redraw micro level label, if needed */
1772 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1773 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1774 strcmp(level.author, leveldir_current->name) != 0 &&
1775 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1777 int max_label_counter = 23;
1779 if (leveldir_current->imported_from != NULL)
1780 max_label_counter += 14;
1782 label_counter = (label_counter + 1) % max_label_counter;
1783 label_state = (label_counter >= 0 && label_counter <= 7 ?
1784 MICROLABEL_LEVEL_NAME :
1785 label_counter >= 9 && label_counter <= 12 ?
1786 MICROLABEL_CREATED_BY :
1787 label_counter >= 14 && label_counter <= 21 ?
1788 MICROLABEL_LEVEL_AUTHOR :
1789 label_counter >= 23 && label_counter <= 26 ?
1790 MICROLABEL_IMPORTED_FROM :
1791 label_counter >= 28 && label_counter <= 35 ?
1792 MICROLABEL_LEVEL_IMPORT_INFO : MICROLABEL_EMPTY);
1793 DrawMicroLevelLabelExt(label_state);
1797 int REQ_in_range(int x, int y)
1799 if (y > DY+249 && y < DY+278)
1801 if (x > DX+1 && x < DX+48)
1803 else if (x > DX+51 && x < DX+98)
1809 boolean Request(char *text, unsigned int req_state)
1811 int mx, my, ty, result = -1;
1812 unsigned int old_door_state;
1815 /* pause network game while waiting for request to answer */
1816 if (options.network &&
1817 game_status == PLAYING &&
1818 req_state & REQUEST_WAIT_FOR)
1819 SendToServer_PausePlaying();
1822 old_door_state = GetDoorState();
1826 CloseDoor(DOOR_CLOSE_1);
1828 /* save old door content */
1829 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1830 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
1831 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
1833 /* clear door drawing field */
1834 XFillRectangle(display, drawto, gc, DX, DY, DXSIZE, DYSIZE);
1836 /* write text for request */
1837 for(ty=0; ty<13; ty++)
1845 for(tl=0,tx=0; tx<7; tl++,tx++)
1848 if (!tc || tc == 32)
1859 DrawTextExt(drawto, gc,
1860 DX + 51 - (tl * 14)/2, DY + 8 + ty * 16,
1861 txt, FS_SMALL, FC_YELLOW);
1862 text += tl + (tc == 32 ? 1 : 0);
1865 if (req_state & REQ_ASK)
1867 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
1868 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
1870 else if (req_state & REQ_CONFIRM)
1872 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
1874 else if (req_state & REQ_PLAYER)
1876 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
1877 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
1878 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
1879 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
1882 /* copy request gadgets to door backbuffer */
1883 XCopyArea(display, drawto, pix[PIX_DB_DOOR], gc,
1884 DX, DY, DXSIZE, DYSIZE,
1885 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1887 OpenDoor(DOOR_OPEN_1);
1893 if (!(req_state & REQUEST_WAIT_FOR))
1896 if (game_status != MAINMENU)
1899 button_status = MB_RELEASED;
1901 request_gadget_id = -1;
1905 if (XPending(display))
1909 XNextEvent(display, &event);
1917 if (event.type == MotionNotify)
1924 if (!XQueryPointer(display, window, &root, &child,
1925 &root_x, &root_y, &win_x, &win_y, &mask))
1931 motion_status = TRUE;
1932 mx = ((XMotionEvent *) &event)->x;
1933 my = ((XMotionEvent *) &event)->y;
1937 motion_status = FALSE;
1938 mx = ((XButtonEvent *) &event)->x;
1939 my = ((XButtonEvent *) &event)->y;
1940 if (event.type==ButtonPress)
1941 button_status = ((XButtonEvent *) &event)->button;
1943 button_status = MB_RELEASED;
1946 /* this sets 'request_gadget_id' */
1947 HandleGadgets(mx, my, button_status);
1949 switch(request_gadget_id)
1951 case TOOL_CTRL_ID_YES:
1954 case TOOL_CTRL_ID_NO:
1957 case TOOL_CTRL_ID_CONFIRM:
1958 result = TRUE | FALSE;
1961 case TOOL_CTRL_ID_PLAYER_1:
1964 case TOOL_CTRL_ID_PLAYER_2:
1967 case TOOL_CTRL_ID_PLAYER_3:
1970 case TOOL_CTRL_ID_PLAYER_4:
1982 switch(XLookupKeysym((XKeyEvent *)&event,
1983 ((XKeyEvent *)&event)->state))
1996 if (req_state & REQ_PLAYER)
2001 key_joystick_mapping = 0;
2005 HandleOtherEvents(&event);
2009 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2011 int joy = AnyJoystick();
2013 if (joy & JOY_BUTTON_1)
2015 else if (joy & JOY_BUTTON_2)
2021 /* don't eat all CPU time */
2025 if (game_status != MAINMENU)
2030 if (!(req_state & REQ_STAY_OPEN))
2032 CloseDoor(DOOR_CLOSE_1);
2034 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
2036 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
2037 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
2038 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
2039 OpenDoor(DOOR_OPEN_1);
2046 /* continue network game after request */
2047 if (options.network &&
2048 game_status == PLAYING &&
2049 req_state & REQUEST_WAIT_FOR)
2050 SendToServer_ContinuePlaying();
2056 unsigned int OpenDoor(unsigned int door_state)
2058 unsigned int new_door_state;
2060 if (door_state & DOOR_COPY_BACK)
2062 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
2063 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
2064 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2065 door_state &= ~DOOR_COPY_BACK;
2068 new_door_state = MoveDoor(door_state);
2070 return(new_door_state);
2073 unsigned int CloseDoor(unsigned int door_state)
2075 unsigned int new_door_state;
2077 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
2078 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2079 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
2080 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2082 new_door_state = MoveDoor(door_state);
2084 return(new_door_state);
2087 unsigned int GetDoorState()
2089 return(MoveDoor(DOOR_GET_STATE));
2092 unsigned int MoveDoor(unsigned int door_state)
2094 static int door1 = DOOR_OPEN_1;
2095 static int door2 = DOOR_CLOSE_2;
2096 static unsigned long door_delay = 0;
2097 int x, start, stepsize = 2;
2098 unsigned long door_delay_value = stepsize * 5;
2100 if (door_state == DOOR_GET_STATE)
2101 return(door1 | door2);
2103 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2104 door_state &= ~DOOR_OPEN_1;
2105 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2106 door_state &= ~DOOR_CLOSE_1;
2107 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2108 door_state &= ~DOOR_OPEN_2;
2109 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2110 door_state &= ~DOOR_CLOSE_2;
2112 if (setup.quick_doors)
2115 door_delay_value = 0;
2116 StopSound(SND_OEFFNEN);
2119 if (door_state & DOOR_ACTION)
2121 if (!(door_state & DOOR_NO_DELAY))
2122 PlaySoundStereo(SND_OEFFNEN, PSND_MAX_RIGHT);
2124 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2126 for(x=start; x<=DXSIZE; x+=stepsize)
2128 WaitUntilDelayReached(&door_delay, door_delay_value);
2130 if (door_state & DOOR_ACTION_1)
2132 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
2133 int j = (DXSIZE - i) / 3;
2135 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
2136 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
2137 DXSIZE,DYSIZE - i/2, DX, DY);
2139 XFillRectangle(display, drawto, gc, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
2141 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2142 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2143 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
2144 DXSIZE, DOOR_GFX_PAGEY1, i, 77, DX + DXSIZE - i, DY + j);
2145 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2146 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63, DX + DXSIZE - i,
2148 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2149 DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
2150 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2151 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j, DX, DY);
2152 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2153 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63, DX, DY + 140 - j);
2155 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2156 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2158 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2159 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2161 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2162 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2163 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2164 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2165 DX + DXSIZE - i, DY + 77 + j);
2166 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2167 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2168 DX + DXSIZE - i, DY + 203 + j);
2170 redraw_mask |= REDRAW_DOOR_1;
2173 if (door_state & DOOR_ACTION_2)
2175 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
2176 int j = (VXSIZE - i) / 3;
2178 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
2179 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
2180 VXSIZE, VYSIZE - i/2, VX, VY);
2182 XFillRectangle(display, drawto, gc, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
2184 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2185 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2186 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2187 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2, VX + VXSIZE-i, VY+j);
2188 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2189 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2190 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
2191 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j, VX, VY);
2193 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2194 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2,
2195 VX, VY + VYSIZE / 2 - j);
2196 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2197 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2198 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2199 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2 - j,
2200 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2202 redraw_mask |= REDRAW_DOOR_2;
2207 if (game_status == MAINMENU)
2212 if (setup.quick_doors)
2213 StopSound(SND_OEFFNEN);
2215 if (door_state & DOOR_ACTION_1)
2216 door1 = door_state & DOOR_ACTION_1;
2217 if (door_state & DOOR_ACTION_2)
2218 door2 = door_state & DOOR_ACTION_2;
2220 return (door1 | door2);
2223 void DrawSpecialEditorDoor()
2225 /* draw bigger toolbox window */
2226 XCopyArea(display, pix[PIX_DOOR], drawto, gc,
2227 DOOR_GFX_PAGEX7, 0, 108, 56, EX - 4, EY - 12);
2229 redraw_mask |= REDRAW_ALL;
2232 void UndrawSpecialEditorDoor()
2234 /* draw normal tape recorder window */
2235 XCopyArea(display, pix[PIX_BACK], drawto, gc,
2236 562, 344, 108, 56, EX - 4, EY - 12);
2238 redraw_mask |= REDRAW_ALL;
2241 int ReadPixel(Drawable d, int x, int y)
2243 XImage *pixel_image;
2244 unsigned long pixel_value;
2246 pixel_image = XGetImage(display, d, x, y, 1, 1, AllPlanes, ZPixmap);
2247 pixel_value = XGetPixel(pixel_image, 0, 0);
2249 XDestroyImage(pixel_image);
2254 /* ---------- new tool button stuff ---------------------------------------- */
2256 /* graphic position values for tool buttons */
2257 #define TOOL_BUTTON_YES_XPOS 2
2258 #define TOOL_BUTTON_YES_YPOS 250
2259 #define TOOL_BUTTON_YES_GFX_YPOS 0
2260 #define TOOL_BUTTON_YES_XSIZE 46
2261 #define TOOL_BUTTON_YES_YSIZE 28
2262 #define TOOL_BUTTON_NO_XPOS 52
2263 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2264 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2265 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2266 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2267 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2268 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2269 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2270 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2271 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2272 #define TOOL_BUTTON_PLAYER_XSIZE 30
2273 #define TOOL_BUTTON_PLAYER_YSIZE 30
2274 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2275 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2276 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2277 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2278 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2279 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2280 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2281 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2282 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2283 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2284 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2285 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2286 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2287 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2288 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2289 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2290 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2291 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2292 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2293 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2302 } toolbutton_info[NUM_TOOL_BUTTONS] =
2305 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2306 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2307 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2312 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2313 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2314 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2319 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2320 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2321 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2322 TOOL_CTRL_ID_CONFIRM,
2326 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2327 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2328 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2329 TOOL_CTRL_ID_PLAYER_1,
2333 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2334 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2335 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2336 TOOL_CTRL_ID_PLAYER_2,
2340 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2341 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2342 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2343 TOOL_CTRL_ID_PLAYER_3,
2347 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2348 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2349 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2350 TOOL_CTRL_ID_PLAYER_4,
2355 static void DoNotDisplayInfoText(void *ptr)
2360 void CreateToolButtons()
2364 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2366 Pixmap gd_pixmap = pix[PIX_DOOR];
2367 Pixmap deco_pixmap = None;
2368 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2369 struct GadgetInfo *gi;
2370 unsigned long event_mask;
2371 int gd_xoffset, gd_yoffset;
2372 int gd_x1, gd_x2, gd_y;
2375 event_mask = GD_EVENT_RELEASED;
2377 gd_xoffset = toolbutton_info[i].xpos;
2378 gd_yoffset = toolbutton_info[i].ypos;
2379 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2380 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2381 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2383 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2385 getMiniGraphicSource(GFX_SPIELER1 + id - TOOL_CTRL_ID_PLAYER_1,
2386 &deco_pixmap, &deco_x, &deco_y);
2387 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2388 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2391 gi = CreateGadget(GDI_CUSTOM_ID, id,
2392 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2393 GDI_X, DX + toolbutton_info[i].x,
2394 GDI_Y, DY + toolbutton_info[i].y,
2395 GDI_WIDTH, toolbutton_info[i].width,
2396 GDI_HEIGHT, toolbutton_info[i].height,
2397 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2398 GDI_STATE, GD_BUTTON_UNPRESSED,
2399 GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y,
2400 GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y,
2401 GDI_DECORATION_DESIGN, deco_pixmap, deco_x, deco_y,
2402 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2403 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2404 GDI_DECORATION_SHIFTING, 1, 1,
2405 GDI_EVENT_MASK, event_mask,
2406 GDI_CALLBACK_ACTION, HandleToolButtons,
2407 GDI_CALLBACK_INFO, DoNotDisplayInfoText,
2411 Error(ERR_EXIT, "cannot create gadget");
2413 tool_gadget[id] = gi;
2417 static void UnmapToolButtons()
2421 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2422 UnmapGadget(tool_gadget[i]);
2425 static void HandleToolButtons(struct GadgetInfo *gi)
2427 request_gadget_id = gi->custom_id;
2430 int el2gfx(int element)
2434 case EL_LEERRAUM: return -1;
2435 case EL_ERDREICH: return GFX_ERDREICH;
2436 case EL_MAUERWERK: return GFX_MAUERWERK;
2437 case EL_FELSBODEN: return GFX_FELSBODEN;
2438 case EL_FELSBROCKEN: return GFX_FELSBROCKEN;
2439 case EL_SCHLUESSEL: return GFX_SCHLUESSEL;
2440 case EL_EDELSTEIN: return GFX_EDELSTEIN;
2441 case EL_AUSGANG_ZU: return GFX_AUSGANG_ZU;
2442 case EL_AUSGANG_ACT: return GFX_AUSGANG_ACT;
2443 case EL_AUSGANG_AUF: return GFX_AUSGANG_AUF;
2444 case EL_SPIELFIGUR: return GFX_SPIELFIGUR;
2445 case EL_SPIELER1: return GFX_SPIELER1;
2446 case EL_SPIELER2: return GFX_SPIELER2;
2447 case EL_SPIELER3: return GFX_SPIELER3;
2448 case EL_SPIELER4: return GFX_SPIELER4;
2449 case EL_KAEFER: return GFX_KAEFER;
2450 case EL_KAEFER_RIGHT: return GFX_KAEFER_RIGHT;
2451 case EL_KAEFER_UP: return GFX_KAEFER_UP;
2452 case EL_KAEFER_LEFT: return GFX_KAEFER_LEFT;
2453 case EL_KAEFER_DOWN: return GFX_KAEFER_DOWN;
2454 case EL_FLIEGER: return GFX_FLIEGER;
2455 case EL_FLIEGER_RIGHT: return GFX_FLIEGER_RIGHT;
2456 case EL_FLIEGER_UP: return GFX_FLIEGER_UP;
2457 case EL_FLIEGER_LEFT: return GFX_FLIEGER_LEFT;
2458 case EL_FLIEGER_DOWN: return GFX_FLIEGER_DOWN;
2459 case EL_BUTTERFLY: return GFX_BUTTERFLY;
2460 case EL_BUTTERFLY_RIGHT: return GFX_BUTTERFLY_RIGHT;
2461 case EL_BUTTERFLY_UP: return GFX_BUTTERFLY_UP;
2462 case EL_BUTTERFLY_LEFT: return GFX_BUTTERFLY_LEFT;
2463 case EL_BUTTERFLY_DOWN: return GFX_BUTTERFLY_DOWN;
2464 case EL_FIREFLY: return GFX_FIREFLY;
2465 case EL_FIREFLY_RIGHT: return GFX_FIREFLY_RIGHT;
2466 case EL_FIREFLY_UP: return GFX_FIREFLY_UP;
2467 case EL_FIREFLY_LEFT: return GFX_FIREFLY_LEFT;
2468 case EL_FIREFLY_DOWN: return GFX_FIREFLY_DOWN;
2469 case EL_MAMPFER: return GFX_MAMPFER;
2470 case EL_ROBOT: return GFX_ROBOT;
2471 case EL_BETON: return GFX_BETON;
2472 case EL_DIAMANT: return GFX_DIAMANT;
2473 case EL_MORAST_LEER: return GFX_MORAST_LEER;
2474 case EL_MORAST_VOLL: return GFX_MORAST_VOLL;
2475 case EL_TROPFEN: return GFX_TROPFEN;
2476 case EL_BOMBE: return GFX_BOMBE;
2477 case EL_MAGIC_WALL_OFF: return GFX_MAGIC_WALL_OFF;
2478 case EL_MAGIC_WALL_EMPTY: return GFX_MAGIC_WALL_EMPTY;
2479 case EL_MAGIC_WALL_FULL: return GFX_MAGIC_WALL_FULL;
2480 case EL_MAGIC_WALL_DEAD: return GFX_MAGIC_WALL_DEAD;
2481 case EL_SALZSAEURE: return GFX_SALZSAEURE;
2482 case EL_AMOEBE_TOT: return GFX_AMOEBE_TOT;
2483 case EL_AMOEBE_NASS: return GFX_AMOEBE_NASS;
2484 case EL_AMOEBE_NORM: return GFX_AMOEBE_NORM;
2485 case EL_AMOEBE_VOLL: return GFX_AMOEBE_VOLL;
2486 case EL_AMOEBE_BD: return GFX_AMOEBE_BD;
2487 case EL_AMOEBA2DIAM: return GFX_AMOEBA2DIAM;
2488 case EL_KOKOSNUSS: return GFX_KOKOSNUSS;
2489 case EL_LIFE: return GFX_LIFE;
2490 case EL_LIFE_ASYNC: return GFX_LIFE_ASYNC;
2491 case EL_DYNAMITE_ACTIVE: return GFX_DYNAMIT;
2492 case EL_BADEWANNE: return GFX_BADEWANNE;
2493 case EL_BADEWANNE1: return GFX_BADEWANNE1;
2494 case EL_BADEWANNE2: return GFX_BADEWANNE2;
2495 case EL_BADEWANNE3: return GFX_BADEWANNE3;
2496 case EL_BADEWANNE4: return GFX_BADEWANNE4;
2497 case EL_BADEWANNE5: return GFX_BADEWANNE5;
2498 case EL_ABLENK_AUS: return GFX_ABLENK_AUS;
2499 case EL_ABLENK_EIN: return GFX_ABLENK_EIN;
2500 case EL_SCHLUESSEL1: return GFX_SCHLUESSEL1;
2501 case EL_SCHLUESSEL2: return GFX_SCHLUESSEL2;
2502 case EL_SCHLUESSEL3: return GFX_SCHLUESSEL3;
2503 case EL_SCHLUESSEL4: return GFX_SCHLUESSEL4;
2504 case EL_PFORTE1: return GFX_PFORTE1;
2505 case EL_PFORTE2: return GFX_PFORTE2;
2506 case EL_PFORTE3: return GFX_PFORTE3;
2507 case EL_PFORTE4: return GFX_PFORTE4;
2508 case EL_PFORTE1X: return GFX_PFORTE1X;
2509 case EL_PFORTE2X: return GFX_PFORTE2X;
2510 case EL_PFORTE3X: return GFX_PFORTE3X;
2511 case EL_PFORTE4X: return GFX_PFORTE4X;
2512 case EL_DYNAMITE_INACTIVE: return GFX_DYNAMIT_AUS;
2513 case EL_PACMAN: return GFX_PACMAN;
2514 case EL_PACMAN_RIGHT: return GFX_PACMAN_RIGHT;
2515 case EL_PACMAN_UP: return GFX_PACMAN_UP;
2516 case EL_PACMAN_LEFT: return GFX_PACMAN_LEFT;
2517 case EL_PACMAN_DOWN: return GFX_PACMAN_DOWN;
2518 case EL_UNSICHTBAR: return GFX_UNSICHTBAR;
2519 case EL_ERZ_EDEL: return GFX_ERZ_EDEL;
2520 case EL_ERZ_DIAM: return GFX_ERZ_DIAM;
2521 case EL_BIRNE_AUS: return GFX_BIRNE_AUS;
2522 case EL_BIRNE_EIN: return GFX_BIRNE_EIN;
2523 case EL_ZEIT_VOLL: return GFX_ZEIT_VOLL;
2524 case EL_ZEIT_LEER: return GFX_ZEIT_LEER;
2525 case EL_MAUER_LEBT: return GFX_MAUER_LEBT;
2526 case EL_MAUER_X: return GFX_MAUER_X;
2527 case EL_MAUER_Y: return GFX_MAUER_Y;
2528 case EL_MAUER_XY: return GFX_MAUER_XY;
2529 case EL_EDELSTEIN_BD: return GFX_EDELSTEIN_BD;
2530 case EL_EDELSTEIN_GELB: return GFX_EDELSTEIN_GELB;
2531 case EL_EDELSTEIN_ROT: return GFX_EDELSTEIN_ROT;
2532 case EL_EDELSTEIN_LILA: return GFX_EDELSTEIN_LILA;
2533 case EL_ERZ_EDEL_BD: return GFX_ERZ_EDEL_BD;
2534 case EL_ERZ_EDEL_GELB: return GFX_ERZ_EDEL_GELB;
2535 case EL_ERZ_EDEL_ROT: return GFX_ERZ_EDEL_ROT;
2536 case EL_ERZ_EDEL_LILA: return GFX_ERZ_EDEL_LILA;
2537 case EL_MAMPFER2: return GFX_MAMPFER2;
2538 case EL_MAGIC_WALL_BD_OFF: return GFX_MAGIC_WALL_BD_OFF;
2539 case EL_MAGIC_WALL_BD_EMPTY:return GFX_MAGIC_WALL_BD_EMPTY;
2540 case EL_MAGIC_WALL_BD_FULL: return GFX_MAGIC_WALL_BD_FULL;
2541 case EL_MAGIC_WALL_BD_DEAD: return GFX_MAGIC_WALL_BD_DEAD;
2542 case EL_DYNABOMB_ACTIVE_1: return GFX_DYNABOMB;
2543 case EL_DYNABOMB_ACTIVE_2: return GFX_DYNABOMB;
2544 case EL_DYNABOMB_ACTIVE_3: return GFX_DYNABOMB;
2545 case EL_DYNABOMB_ACTIVE_4: return GFX_DYNABOMB;
2546 case EL_DYNABOMB_NR: return GFX_DYNABOMB_NR;
2547 case EL_DYNABOMB_SZ: return GFX_DYNABOMB_SZ;
2548 case EL_DYNABOMB_XL: return GFX_DYNABOMB_XL;
2549 case EL_SOKOBAN_OBJEKT: return GFX_SOKOBAN_OBJEKT;
2550 case EL_SOKOBAN_FELD_LEER: return GFX_SOKOBAN_FELD_LEER;
2551 case EL_SOKOBAN_FELD_VOLL: return GFX_SOKOBAN_FELD_VOLL;
2552 case EL_MOLE: return GFX_MOLE;
2553 case EL_PINGUIN: return GFX_PINGUIN;
2554 case EL_SCHWEIN: return GFX_SCHWEIN;
2555 case EL_DRACHE: return GFX_DRACHE;
2556 case EL_SONDE: return GFX_SONDE;
2557 case EL_PFEIL_LEFT: return GFX_PFEIL_LEFT;
2558 case EL_PFEIL_RIGHT: return GFX_PFEIL_RIGHT;
2559 case EL_PFEIL_UP: return GFX_PFEIL_UP;
2560 case EL_PFEIL_DOWN: return GFX_PFEIL_DOWN;
2561 case EL_SPEED_PILL: return GFX_SPEED_PILL;
2562 case EL_SP_TERMINAL_ACTIVE: return GFX_SP_TERMINAL;
2563 case EL_SP_BUG_ACTIVE: return GFX_SP_BUG_ACTIVE;
2564 case EL_SP_ZONK: return GFX_SP_ZONK;
2565 /* ^^^^^^^^^^ non-standard position in supaplex graphic set! */
2566 case EL_INVISIBLE_STEEL: return GFX_INVISIBLE_STEEL;
2567 case EL_BLACK_ORB: return GFX_BLACK_ORB;
2568 case EL_EM_GATE_1: return GFX_EM_GATE_1;
2569 case EL_EM_GATE_2: return GFX_EM_GATE_2;
2570 case EL_EM_GATE_3: return GFX_EM_GATE_3;
2571 case EL_EM_GATE_4: return GFX_EM_GATE_4;
2572 case EL_EM_GATE_1X: return GFX_EM_GATE_1X;
2573 case EL_EM_GATE_2X: return GFX_EM_GATE_2X;
2574 case EL_EM_GATE_3X: return GFX_EM_GATE_3X;
2575 case EL_EM_GATE_4X: return GFX_EM_GATE_4X;
2576 case EL_EM_KEY_1_FILE: return GFX_EM_KEY_1;
2577 case EL_EM_KEY_2_FILE: return GFX_EM_KEY_2;
2578 case EL_EM_KEY_3_FILE: return GFX_EM_KEY_3;
2579 case EL_EM_KEY_4_FILE: return GFX_EM_KEY_4;
2580 case EL_EM_KEY_1: return GFX_EM_KEY_1;
2581 case EL_EM_KEY_2: return GFX_EM_KEY_2;
2582 case EL_EM_KEY_3: return GFX_EM_KEY_3;
2583 case EL_EM_KEY_4: return GFX_EM_KEY_4;
2584 case EL_PEARL: return GFX_PEARL;
2585 case EL_CRYSTAL: return GFX_CRYSTAL;
2586 case EL_WALL_PEARL: return GFX_WALL_PEARL;
2587 case EL_WALL_CRYSTAL: return GFX_WALL_CRYSTAL;
2588 case EL_DOOR_WHITE: return GFX_DOOR_WHITE;
2589 case EL_DOOR_WHITE_GRAY: return GFX_DOOR_WHITE_GRAY;
2590 case EL_KEY_WHITE: return GFX_KEY_WHITE;
2591 case EL_SHIELD_PASSIVE: return GFX_SHIELD_PASSIVE;
2592 case EL_SHIELD_ACTIVE: return GFX_SHIELD_ACTIVE;
2593 case EL_EXTRA_TIME: return GFX_EXTRA_TIME;
2594 case EL_SWITCHGATE_OPEN: return GFX_SWITCHGATE_OPEN;
2595 case EL_SWITCHGATE_CLOSED: return GFX_SWITCHGATE_CLOSED;
2596 case EL_SWITCHGATE_SWITCH_1:return GFX_SWITCHGATE_SWITCH_1;
2597 case EL_SWITCHGATE_SWITCH_2:return GFX_SWITCHGATE_SWITCH_2;
2598 case EL_BELT1_LEFT: return GFX_BELT1_LEFT;
2599 case EL_BELT1_MIDDLE: return GFX_BELT1_MIDDLE;
2600 case EL_BELT1_RIGHT: return GFX_BELT1_RIGHT;
2601 case EL_BELT1_SWITCH_LEFT: return GFX_BELT1_SWITCH_LEFT;
2602 case EL_BELT1_SWITCH_MIDDLE:return GFX_BELT1_SWITCH_MIDDLE;
2603 case EL_BELT1_SWITCH_RIGHT: return GFX_BELT1_SWITCH_RIGHT;
2604 case EL_BELT2_LEFT: return GFX_BELT2_LEFT;
2605 case EL_BELT2_MIDDLE: return GFX_BELT2_MIDDLE;
2606 case EL_BELT2_RIGHT: return GFX_BELT2_RIGHT;
2607 case EL_BELT2_SWITCH_LEFT: return GFX_BELT2_SWITCH_LEFT;
2608 case EL_BELT2_SWITCH_MIDDLE:return GFX_BELT2_SWITCH_MIDDLE;
2609 case EL_BELT2_SWITCH_RIGHT: return GFX_BELT2_SWITCH_RIGHT;
2610 case EL_BELT3_LEFT: return GFX_BELT3_LEFT;
2611 case EL_BELT3_MIDDLE: return GFX_BELT3_MIDDLE;
2612 case EL_BELT3_RIGHT: return GFX_BELT3_RIGHT;
2613 case EL_BELT3_SWITCH_LEFT: return GFX_BELT3_SWITCH_LEFT;
2614 case EL_BELT3_SWITCH_MIDDLE:return GFX_BELT3_SWITCH_MIDDLE;
2615 case EL_BELT3_SWITCH_RIGHT: return GFX_BELT3_SWITCH_RIGHT;
2616 case EL_BELT4_LEFT: return GFX_BELT4_LEFT;
2617 case EL_BELT4_MIDDLE: return GFX_BELT4_MIDDLE;
2618 case EL_BELT4_RIGHT: return GFX_BELT4_RIGHT;
2619 case EL_BELT4_SWITCH_LEFT: return GFX_BELT4_SWITCH_LEFT;
2620 case EL_BELT4_SWITCH_MIDDLE:return GFX_BELT4_SWITCH_MIDDLE;
2621 case EL_BELT4_SWITCH_RIGHT: return GFX_BELT4_SWITCH_RIGHT;
2622 case EL_LANDMINE: return GFX_LANDMINE;
2623 case EL_ENVELOPE: return GFX_ENVELOPE;
2624 case EL_LIGHT_SWITCH_OFF: return GFX_LIGHT_SWITCH_OFF;
2625 case EL_LIGHT_SWITCH_ON: return GFX_LIGHT_SWITCH_ON;
2626 case EL_SIGN_EXCLAMATION: return GFX_SIGN_EXCLAMATION;
2627 case EL_SIGN_RADIOACTIVITY: return GFX_SIGN_RADIOACTIVITY;
2628 case EL_SIGN_STOP: return GFX_SIGN_STOP;
2629 case EL_SIGN_WHEELCHAIR: return GFX_SIGN_WHEELCHAIR;
2630 case EL_SIGN_PARKING: return GFX_SIGN_PARKING;
2631 case EL_SIGN_ONEWAY: return GFX_SIGN_ONEWAY;
2632 case EL_SIGN_HEART: return GFX_SIGN_HEART;
2633 case EL_SIGN_TRIANGLE: return GFX_SIGN_TRIANGLE;
2634 case EL_SIGN_ROUND: return GFX_SIGN_ROUND;
2635 case EL_SIGN_EXIT: return GFX_SIGN_EXIT;
2636 case EL_SIGN_YINYANG: return GFX_SIGN_YINYANG;
2637 case EL_SIGN_OTHER: return GFX_SIGN_OTHER;
2638 case EL_MOLE_LEFT: return GFX_MOLE_LEFT;
2639 case EL_MOLE_RIGHT: return GFX_MOLE_RIGHT;
2640 case EL_MOLE_UP: return GFX_MOLE_UP;
2641 case EL_MOLE_DOWN: return GFX_MOLE_DOWN;
2642 case EL_STEEL_SLANTED: return GFX_STEEL_SLANTED;
2643 case EL_SAND_INVISIBLE: return GFX_SAND_INVISIBLE;
2644 case EL_DX_UNKNOWN_15: return GFX_DX_UNKNOWN_15;
2645 case EL_DX_UNKNOWN_42: return GFX_DX_UNKNOWN_42;
2646 case EL_TIMEGATE_OPEN: return GFX_TIMEGATE_OPEN;
2647 case EL_TIMEGATE_CLOSED: return GFX_TIMEGATE_CLOSED;
2648 case EL_TIMEGATE_SWITCH_ON: return GFX_TIMEGATE_SWITCH;
2649 case EL_TIMEGATE_SWITCH_OFF:return GFX_TIMEGATE_SWITCH;
2650 case EL_BALLOON: return GFX_BALLOON;
2651 case EL_BALLOON_SEND_LEFT: return GFX_BALLOON_SEND_LEFT;
2652 case EL_BALLOON_SEND_RIGHT: return GFX_BALLOON_SEND_RIGHT;
2653 case EL_BALLOON_SEND_UP: return GFX_BALLOON_SEND_UP;
2654 case EL_BALLOON_SEND_DOWN: return GFX_BALLOON_SEND_DOWN;
2655 case EL_BALLOON_SEND_ANY: return GFX_BALLOON_SEND_ANY;
2656 case EL_EMC_STEEL_WALL_1: return GFX_EMC_STEEL_WALL_1;
2657 case EL_EMC_STEEL_WALL_2: return GFX_EMC_STEEL_WALL_2;
2658 case EL_EMC_STEEL_WALL_3: return GFX_EMC_STEEL_WALL_3;
2659 case EL_EMC_STEEL_WALL_4: return GFX_EMC_STEEL_WALL_4;
2660 case EL_EMC_WALL_1: return GFX_EMC_WALL_1;
2661 case EL_EMC_WALL_2: return GFX_EMC_WALL_2;
2662 case EL_EMC_WALL_3: return GFX_EMC_WALL_3;
2663 case EL_EMC_WALL_4: return GFX_EMC_WALL_4;
2664 case EL_EMC_WALL_5: return GFX_EMC_WALL_5;
2665 case EL_EMC_WALL_6: return GFX_EMC_WALL_6;
2666 case EL_EMC_WALL_7: return GFX_EMC_WALL_7;
2667 case EL_EMC_WALL_8: return GFX_EMC_WALL_8;
2668 case EL_TUBE_CROSS: return GFX_TUBE_CROSS;
2669 case EL_TUBE_VERTICAL: return GFX_TUBE_VERTICAL;
2670 case EL_TUBE_HORIZONTAL: return GFX_TUBE_HORIZONTAL;
2671 case EL_TUBE_VERT_LEFT: return GFX_TUBE_VERT_LEFT;
2672 case EL_TUBE_VERT_RIGHT: return GFX_TUBE_VERT_RIGHT;
2673 case EL_TUBE_HORIZ_UP: return GFX_TUBE_HORIZ_UP;
2674 case EL_TUBE_HORIZ_DOWN: return GFX_TUBE_HORIZ_DOWN;
2675 case EL_TUBE_LEFT_UP: return GFX_TUBE_LEFT_UP;
2676 case EL_TUBE_LEFT_DOWN: return GFX_TUBE_LEFT_DOWN;
2677 case EL_TUBE_RIGHT_UP: return GFX_TUBE_RIGHT_UP;
2678 case EL_TUBE_RIGHT_DOWN: return GFX_TUBE_RIGHT_DOWN;
2679 case EL_SPRING: return GFX_SPRING;
2680 case EL_SPRING_MOVING: return GFX_SPRING;
2681 case EL_TRAP_INACTIVE: return GFX_TRAP_INACTIVE;
2682 case EL_TRAP_ACTIVE: return GFX_TRAP_ACTIVE;
2683 case EL_BD_WALL: return GFX_BD_WALL;
2684 case EL_BD_ROCK: return GFX_BD_ROCK;
2685 case EL_DX_SUPABOMB: return GFX_DX_SUPABOMB;
2686 case EL_SP_MURPHY_CLONE: return GFX_SP_MURPHY_CLONE;
2690 if (IS_CHAR(element))
2691 return GFX_CHAR_START + (element - EL_CHAR_START);
2692 else if (element >= EL_SP_START && element <= EL_SP_END)
2694 int nr_element = element - EL_SP_START;
2695 int gfx_per_line = 8;
2697 (nr_element / gfx_per_line) * SP_PER_LINE +
2698 (nr_element % gfx_per_line);
2700 return GFX_START_ROCKSSP + nr_graphic;