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 UnmapToolButtons();
48 static void HandleToolButtons(struct GadgetInfo *);
50 static struct GadgetInfo *tool_gadget[NUM_TOOL_BUTTONS];
51 static int request_gadget_id = -1;
53 void SetDrawtoField(int mode)
55 if (mode == DRAW_BUFFERED && setup.soft_scrolling)
66 drawto_field = fieldbuffer;
68 else /* DRAW_DIRECT, DRAW_BACKBUFFER */
79 drawto_field = (mode == DRAW_DIRECT ? window : backbuffer);
86 Drawable buffer = (drawto_field == window ? backbuffer : drawto_field);
88 if (setup.direct_draw && game_status == PLAYING)
89 redraw_mask &= ~REDRAW_MAIN;
91 if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD)
92 redraw_mask |= REDRAW_FIELD;
94 if (redraw_mask & REDRAW_FIELD)
95 redraw_mask &= ~REDRAW_TILES;
98 if (redraw_mask & REDRAW_FIELD ||
99 (ScreenGfxPos && setup.soft_scrolling && game_status == PLAYING))
100 redraw_mask &= ~REDRAW_TILES;
106 /* synchronize X11 graphics at this point; if we would synchronize the
107 display immediately after the buffer switching (after the XFlush),
108 this could mean that we have to wait for the graphics to complete,
109 although we could go on doing calculations for the next frame */
111 XSync(display, FALSE);
115 wait_for_vsync = TRUE;
119 if (redraw_mask & REDRAW_ALL)
121 XCopyArea(display, backbuffer, window, gc,
122 0, 0, WIN_XSIZE, WIN_YSIZE,
127 if (redraw_mask & REDRAW_FIELD)
129 if (game_status != PLAYING || redraw_mask & REDRAW_FROM_BACKBUFFER)
131 XCopyArea(display, backbuffer, window, gc,
132 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
137 int fx = FX, fy = FY;
139 if (setup.soft_scrolling)
141 fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
142 fy += (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
145 if (setup.soft_scrolling ||
146 ABS(ScreenMovPos) + ScrollStepSize == TILEX ||
147 ABS(ScreenMovPos) == ScrollStepSize ||
148 redraw_tiles > REDRAWTILES_THRESHOLD)
150 XCopyArea(display, buffer, window, gc, fx, fy, SXSIZE, SYSIZE, SX, SY);
154 printf("redrawing all (ScreenGfxPos == %d) because %s\n",
156 (setup.soft_scrolling ?
157 "setup.soft_scrolling" :
158 ABS(ScreenGfxPos) + ScrollStepSize == TILEX ?
159 "ABS(ScreenGfxPos) + ScrollStepSize == TILEX" :
160 ABS(ScreenGfxPos) == ScrollStepSize ?
161 "ABS(ScreenGfxPos) == ScrollStepSize" :
162 "redraw_tiles > REDRAWTILES_THRESHOLD"));
167 redraw_mask &= ~REDRAW_MAIN;
170 if (redraw_mask & REDRAW_DOORS)
172 if (redraw_mask & REDRAW_DOOR_1)
173 XCopyArea(display, backbuffer, window, gc,
174 DX, DY, DXSIZE, DYSIZE,
176 if (redraw_mask & REDRAW_DOOR_2)
178 if ((redraw_mask & REDRAW_DOOR_2) == REDRAW_DOOR_2)
179 XCopyArea(display,backbuffer,window,gc,
180 VX,VY, VXSIZE,VYSIZE,
184 if (redraw_mask & REDRAW_VIDEO_1)
185 XCopyArea(display,backbuffer,window,gc,
186 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS,
187 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
188 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS);
189 if (redraw_mask & REDRAW_VIDEO_2)
190 XCopyArea(display,backbuffer,window,gc,
191 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS,
192 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
193 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS);
194 if (redraw_mask & REDRAW_VIDEO_3)
195 XCopyArea(display,backbuffer,window,gc,
196 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS,
197 VIDEO_CONTROL_XSIZE,VIDEO_CONTROL_YSIZE,
198 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS);
201 if (redraw_mask & REDRAW_DOOR_3)
202 XCopyArea(display, backbuffer, window, gc,
203 EX, EY, EXSIZE, EYSIZE,
205 redraw_mask &= ~REDRAW_DOORS;
208 if (redraw_mask & REDRAW_MICROLEVEL)
210 XCopyArea(display,backbuffer,window,gc,
211 MICROLEV_XPOS, MICROLEV_YPOS, MICROLEV_XSIZE, MICROLEV_YSIZE,
212 MICROLEV_XPOS, MICROLEV_YPOS);
213 XCopyArea(display,backbuffer,window,gc,
214 SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE,
215 SX, MICROLABEL_YPOS);
216 redraw_mask &= ~REDRAW_MICROLEVEL;
219 if (redraw_mask & REDRAW_TILES)
221 for(x=0; x<SCR_FIELDX; x++)
222 for(y=0; y<SCR_FIELDY; y++)
223 if (redraw[redraw_x1 + x][redraw_y1 + y])
224 XCopyArea(display, buffer, window, gc,
225 FX + x * TILEX, FX + y * TILEY, TILEX, TILEY,
226 SX + x * TILEX, SY + y * TILEY);
231 for(x=0; x<MAX_BUF_XSIZE; x++)
232 for(y=0; y<MAX_BUF_YSIZE; y++)
241 long fading_delay = 300;
243 if (setup.fading && (redraw_mask & REDRAW_FIELD))
250 XFillRectangle(display,window,gc,
251 REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
254 for(i=0;i<2*FULL_SYSIZE;i++)
256 for(y=0;y<FULL_SYSIZE;y++)
258 XCopyArea(display,backbuffer,window,gc,
259 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
267 for(i=1;i<FULL_SYSIZE;i+=2)
268 XCopyArea(display,backbuffer,window,gc,
269 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
275 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,0);
276 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
277 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
281 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,-1);
282 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
283 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
287 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,-1);
288 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
289 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
293 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,0);
294 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
295 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
299 redraw_mask &= ~REDRAW_MAIN;
308 XFillRectangle(display, backbuffer, gc,
309 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
311 if (setup.soft_scrolling && game_status == PLAYING)
313 XFillRectangle(display, fieldbuffer, gc, 0, 0, FXSIZE, FYSIZE);
314 SetDrawtoField(DRAW_BUFFERED);
317 SetDrawtoField(DRAW_BACKBUFFER);
319 if (setup.direct_draw && game_status == PLAYING)
321 XFillRectangle(display, window, gc,
322 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
323 SetDrawtoField(DRAW_DIRECT);
326 redraw_mask |= REDRAW_FIELD;
329 void DrawTextFCentered(int y, int font_type, char *format, ...)
331 char buffer[FULL_SXSIZE / FONT3_XSIZE + 10];
335 font_xsize = (font_type < FC_SPECIAL1 ? FONT2_XSIZE :
336 font_type < FC_SPECIAL2 ? FONT3_XSIZE : FONT4_XSIZE);
338 va_start(ap, format);
339 vsprintf(buffer, format, ap);
342 DrawText(SX + (SXSIZE - strlen(buffer) * font_xsize) / 2, SY + y,
343 buffer, FS_SMALL, font_type);
346 void DrawTextF(int x, int y, int font_type, char *format, ...)
348 char buffer[FULL_SXSIZE / FONT3_XSIZE + 10];
351 va_start(ap, format);
352 vsprintf(buffer, format, ap);
355 DrawText(SX + x, SY + y, buffer, FS_SMALL, font_type);
358 void DrawText(int x, int y, char *text, int font_size, int font_type)
360 DrawTextExt(drawto, gc, x, y, text, font_size, font_type);
363 redraw_mask |= REDRAW_FIELD;
365 redraw_mask |= REDRAW_DOOR_1;
368 void DrawTextExt(Drawable d, GC gc, int x, int y,
369 char *text, int font_size, int font_type)
371 int font_width, font_height, font_start;
373 boolean print_inverse = FALSE;
375 if (font_size != FS_SMALL && font_size != FS_BIG)
376 font_size = FS_SMALL;
377 if (font_type < FC_RED || font_type > FC_SPECIAL2)
380 font_width = (font_size == FS_BIG ? FONT1_XSIZE :
381 font_type < FC_SPECIAL1 ? FONT2_XSIZE :
382 font_type < FC_SPECIAL2 ? FONT3_XSIZE : FONT4_XSIZE);
383 font_height = (font_size == FS_BIG ? FONT1_XSIZE :
384 font_type < FC_SPECIAL2 ? FONT2_XSIZE : FONT4_XSIZE);
385 font_pixmap = (font_size == FS_BIG ? PIX_BIGFONT : PIX_SMALLFONT);
386 font_start = (font_type * (font_size == FS_BIG ? FONT1_YSIZE : FONT2_YSIZE) *
387 FONT_LINES_PER_FONT);
393 if (c == '~' && font_size == FS_SMALL && font_type <= FC_YELLOW)
395 print_inverse = TRUE;
399 if (c >= 'a' && c <= 'z')
401 else if (c == 'ä' || c == 'Ä')
403 else if (c == 'ö' || c == 'Ö')
405 else if (c == 'ü' || c == 'Ü')
408 if (c >= 32 && c <= 95)
410 int src_x = ((c - 32) % FONT_CHARS_PER_LINE) * font_width;
411 int src_y = ((c - 32) / FONT_CHARS_PER_LINE) * font_height + font_start;
412 int dest_x = x, dest_y = y;
416 XCopyArea(display, pix[font_pixmap], d, gc,
417 FONT_CHARS_PER_LINE * font_width,
418 3 * font_height + font_start,
419 font_width, font_height, x, y);
421 XSetClipOrigin(display, clip_gc[font_pixmap],
422 dest_x - src_x, dest_y - src_y);
423 XCopyArea(display, pix[font_pixmap], d, clip_gc[font_pixmap],
424 0, 0, font_width, font_height, dest_x, dest_y);
427 XCopyArea(display, pix[font_pixmap], d, gc,
428 src_x, src_y, font_width, font_height, dest_x, dest_y);
435 void DrawAllPlayers()
439 for(i=0; i<MAX_PLAYERS; i++)
440 if (stored_player[i].active)
441 DrawPlayer(&stored_player[i]);
444 void DrawPlayerField(int x, int y)
449 DrawPlayer(PLAYERINFO(x,y));
452 void DrawPlayer(struct PlayerInfo *player)
454 int jx = player->jx, jy = player->jy;
455 int last_jx = player->last_jx, last_jy = player->last_jy;
456 int next_jx = jx + (jx - last_jx), next_jy = jy + (jy - last_jy);
457 int sx = SCREENX(jx), sy = SCREENY(jy);
458 int sxx = 0, syy = 0;
459 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
461 boolean player_is_moving = (last_jx != jx || last_jy != jy ? TRUE : FALSE);
463 if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
467 if (!IN_LEV_FIELD(jx,jy))
469 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
470 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
471 printf("DrawPlayerField(): This should never happen!\n");
476 if (element == EL_EXPLODING)
479 /* draw things in the field the player is leaving, if needed */
482 if (last_jx != jx || last_jy != jy)
485 if (player_is_moving)
487 if (Store[last_jx][last_jy] && IS_DRAWABLE(last_element))
489 DrawLevelElement(last_jx, last_jy, Store[last_jx][last_jy]);
490 DrawLevelFieldThruMask(last_jx, last_jy);
492 else if (last_element == EL_DYNAMIT)
493 DrawDynamite(last_jx, last_jy);
495 DrawLevelField(last_jx, last_jy);
497 if (player->Pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
501 if (Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
502 DrawLevelElement(next_jx, next_jy, EL_SOKOBAN_FELD_LEER);
504 DrawLevelElement(next_jx, next_jy, EL_LEERRAUM);
507 DrawLevelField(next_jx, next_jy);
511 if (!IN_SCR_FIELD(sx, sy))
514 if (setup.direct_draw)
515 SetDrawtoField(DRAW_BUFFERED);
517 /* draw things behind the player, if needed */
520 DrawLevelElement(jx, jy, Store[jx][jy]);
521 else if (element != EL_DYNAMIT && element != EL_DYNABOMB)
522 DrawLevelField(jx, jy);
524 /* draw player himself */
526 if (game.emulation == EMU_SUPAPLEX)
528 static int last_dir = MV_LEFT;
529 int action = (player->programmed_action ? player->programmed_action :
531 boolean action_moving =
533 ((action & (MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN)) &&
534 !(action & ~(MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN))));
536 graphic = GFX_SP_MURPHY;
540 if (player->MovDir == MV_LEFT)
541 graphic = GFX_MURPHY_PUSH_LEFT;
542 else if (player->MovDir == MV_RIGHT)
543 graphic = GFX_MURPHY_PUSH_RIGHT;
544 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
545 graphic = GFX_MURPHY_PUSH_LEFT;
546 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
547 graphic = GFX_MURPHY_PUSH_RIGHT;
549 else if (player->snapped)
551 if (player->MovDir == MV_LEFT)
552 graphic = GFX_MURPHY_SNAP_LEFT;
553 else if (player->MovDir == MV_RIGHT)
554 graphic = GFX_MURPHY_SNAP_RIGHT;
555 else if (player->MovDir == MV_UP)
556 graphic = GFX_MURPHY_SNAP_UP;
557 else if (player->MovDir == MV_DOWN)
558 graphic = GFX_MURPHY_SNAP_DOWN;
560 else if (action_moving)
562 if (player->MovDir == MV_LEFT)
563 graphic = GFX_MURPHY_GO_LEFT;
564 else if (player->MovDir == MV_RIGHT)
565 graphic = GFX_MURPHY_GO_RIGHT;
566 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
567 graphic = GFX_MURPHY_GO_LEFT;
568 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
569 graphic = GFX_MURPHY_GO_RIGHT;
571 graphic += getGraphicAnimationPhase(3, 2, ANIM_OSCILLATE);
574 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
575 last_dir = player->MovDir;
579 if (player->MovDir == MV_LEFT)
581 (player->Pushing ? GFX_SPIELER1_PUSH_LEFT : GFX_SPIELER1_LEFT);
582 else if (player->MovDir == MV_RIGHT)
584 (player->Pushing ? GFX_SPIELER1_PUSH_RIGHT : GFX_SPIELER1_RIGHT);
585 else if (player->MovDir == MV_UP)
586 graphic = GFX_SPIELER1_UP;
587 else /* MV_DOWN || MV_NO_MOVING */
588 graphic = GFX_SPIELER1_DOWN;
590 graphic += player->index_nr * 3 * HEROES_PER_LINE;
591 graphic += player->Frame;
596 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
597 sxx = player->GfxPos;
599 syy = player->GfxPos;
602 if (!setup.soft_scrolling && ScreenMovPos)
605 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, NO_CUTTING);
607 if (player->Pushing && player->GfxPos)
609 int px = SCREENX(next_jx), py = SCREENY(next_jy);
611 if (element == EL_SOKOBAN_FELD_LEER ||
612 Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
613 DrawGraphicShiftedThruMask(px, py, sxx, syy, GFX_SOKOBAN_OBJEKT,
617 int element = Feld[next_jx][next_jy];
618 int graphic = el2gfx(element);
620 if ((element == EL_FELSBROCKEN || element == EL_SP_ZONK) && sxx)
622 int phase = (player->GfxPos / (TILEX / 4));
624 if (player->MovDir == MV_LEFT)
627 graphic += (phase + 4) % 4;
630 DrawGraphicShifted(px, py, sxx, syy, graphic, NO_CUTTING, NO_MASKING);
634 /* draw things in front of player (EL_DYNAMIT or EL_DYNABOMB) */
636 if (element == EL_DYNAMIT || element == EL_DYNABOMB)
638 graphic = el2gfx(element);
640 if (element == EL_DYNAMIT)
642 if ((phase = (96 - MovDelay[jx][jy]) / 12) > 6)
647 if ((phase = ((96 - MovDelay[jx][jy]) / 6) % 8) > 3)
651 if (game.emulation == EMU_SUPAPLEX)
652 DrawGraphic(sx, sy, GFX_SP_DISK_RED);
654 DrawGraphicThruMask(sx, sy, graphic + phase);
658 if ((last_jx != jx || last_jy != jy) && last_element == EL_EXPLODING)
661 if (player_is_moving && last_element == EL_EXPLODING)
663 int phase = Frame[last_jx][last_jy];
667 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy),
668 GFX_EXPLOSION + ((phase - 1) / delay - 1));
671 /* draw elements that stay over the player */
672 /* handle the field the player is leaving ... */
673 if (player_is_moving && IS_OVER_PLAYER(last_element))
674 DrawLevelField(last_jx, last_jy);
675 /* ... and the field the player is entering */
676 if (IS_OVER_PLAYER(element))
677 DrawLevelField(jx, jy);
679 if (setup.direct_draw)
681 int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
682 int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
683 int x_size = TILEX * (1 + ABS(jx - last_jx));
684 int y_size = TILEY * (1 + ABS(jy - last_jy));
686 XCopyArea(display, drawto_field, window, gc,
687 dest_x, dest_y, x_size, y_size, dest_x, dest_y);
688 SetDrawtoField(DRAW_DIRECT);
691 MarkTileDirty(sx,sy);
694 static int getGraphicAnimationPhase(int frames, int delay, int mode)
698 if (mode == ANIM_OSCILLATE)
700 int max_anim_frames = 2 * frames - 2;
701 phase = (FrameCounter % (delay * max_anim_frames)) / delay;
702 phase = (phase < frames ? phase : max_anim_frames - phase);
705 phase = (FrameCounter % (delay * frames)) / delay;
707 if (mode == ANIM_REVERSE)
713 void DrawGraphicAnimationExt(int x, int y, int graphic,
714 int frames, int delay, int mode, int mask_mode)
716 int phase = getGraphicAnimationPhase(frames, delay, mode);
718 if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
720 if (mask_mode == USE_MASKING)
721 DrawGraphicThruMask(SCREENX(x), SCREENY(y), graphic + phase);
723 DrawGraphic(SCREENX(x), SCREENY(y), graphic + phase);
727 void DrawGraphicAnimation(int x, int y, int graphic,
728 int frames, int delay, int mode)
730 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, NO_MASKING);
733 void DrawGraphicAnimationThruMask(int x, int y, int graphic,
734 int frames, int delay, int mode)
736 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, USE_MASKING);
739 void getGraphicSource(int graphic, int *pixmap_nr, int *x, int *y)
741 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
743 graphic -= GFX_START_ROCKSSCREEN;
744 *pixmap_nr = PIX_BACK;
745 *x = SX + (graphic % GFX_PER_LINE) * TILEX;
746 *y = SY + (graphic / GFX_PER_LINE) * TILEY;
748 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
750 graphic -= GFX_START_ROCKSMORE;
751 *pixmap_nr = PIX_MORE;
752 *x = (graphic % MORE_PER_LINE) * TILEX;
753 *y = (graphic / MORE_PER_LINE) * TILEY;
755 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
757 graphic -= GFX_START_ROCKSHEROES;
758 *pixmap_nr = PIX_HEROES;
759 *x = (graphic % HEROES_PER_LINE) * TILEX;
760 *y = (graphic / HEROES_PER_LINE) * TILEY;
762 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
764 graphic -= GFX_START_ROCKSFONT;
765 *pixmap_nr = PIX_BIGFONT;
766 *x = (graphic % FONT_CHARS_PER_LINE) * TILEX;
767 *y = ((graphic / FONT_CHARS_PER_LINE) * TILEY +
768 FC_SPECIAL1 * FONT_LINES_PER_FONT * TILEY);
772 *pixmap_nr = PIX_MORE;
778 void DrawGraphic(int x, int y, int graphic)
781 if (!IN_SCR_FIELD(x,y))
783 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
784 printf("DrawGraphic(): This should never happen!\n");
789 DrawGraphicExt(drawto_field, gc, FX + x*TILEX, FY + y*TILEY, graphic);
793 void DrawGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
801 getGraphicSource(graphic, &pixmap_nr, &src_x, &src_y);
802 XCopyArea(display, pix[pixmap_nr], d, gc,
803 src_x, src_y, TILEX, TILEY, x, y);
807 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
809 graphic -= GFX_START_ROCKSSCREEN;
810 XCopyArea(display, pix[PIX_BACK], d, gc,
811 SX + (graphic % GFX_PER_LINE) * TILEX,
812 SY + (graphic / GFX_PER_LINE) * TILEY,
815 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
817 graphic -= GFX_START_ROCKSMORE;
818 XCopyArea(display, pix[PIX_MORE], d, gc,
819 (graphic % MORE_PER_LINE) * TILEX,
820 (graphic / MORE_PER_LINE) * TILEY,
823 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
825 graphic -= GFX_START_ROCKSHEROES;
826 XCopyArea(display, pix[PIX_HEROES], d, gc,
827 (graphic % HEROES_PER_LINE) * TILEX,
828 (graphic / HEROES_PER_LINE) * TILEY,
831 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
833 graphic -= GFX_START_ROCKSFONT;
834 XCopyArea(display, pix[PIX_BIGFONT], d, gc,
835 (graphic % FONT_CHARS_PER_LINE) * TILEX,
836 (graphic / FONT_CHARS_PER_LINE) * TILEY +
837 FC_SPECIAL1 * FONT_LINES_PER_FONT * TILEY,
841 XFillRectangle(display, d, gc, x, y, TILEX, TILEY);
847 void DrawGraphicThruMask(int x, int y, int graphic)
850 if (!IN_SCR_FIELD(x,y))
852 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
853 printf("DrawGraphicThruMask(): This should never happen!\n");
858 DrawGraphicThruMaskExt(drawto_field, FX + x*TILEX, FY + y*TILEY, graphic);
862 void DrawGraphicThruMaskExt(Drawable d, int dest_x, int dest_y, int graphic)
873 if (graphic == GFX_LEERRAUM)
876 getGraphicSource(graphic, &pixmap_nr, &src_x, &src_y);
877 src_pixmap = pix[pixmap_nr];
878 drawing_gc = clip_gc[pixmap_nr];
887 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
889 src_pixmap = pix[PIX_BACK];
890 drawing_gc = clip_gc[PIX_BACK];
891 graphic -= GFX_START_ROCKSSCREEN;
892 src_x = SX + (graphic % GFX_PER_LINE) * TILEX;
893 src_y = SY + (graphic / GFX_PER_LINE) * TILEY;
895 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
897 src_pixmap = pix[PIX_MORE];
898 drawing_gc = clip_gc[PIX_MORE];
899 graphic -= GFX_START_ROCKSMORE;
900 src_x = (graphic % MORE_PER_LINE) * TILEX;
901 src_y = (graphic / MORE_PER_LINE) * TILEY;
903 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
905 src_pixmap = pix[PIX_HEROES];
906 drawing_gc = clip_gc[PIX_HEROES];
907 graphic -= GFX_START_ROCKSHEROES;
908 src_x = (graphic % HEROES_PER_LINE) * TILEX;
909 src_y = (graphic / HEROES_PER_LINE) * TILEY;
913 DrawGraphicExt(d, gc, dest_x,dest_y, graphic);
920 if (tile_clipmask[tile] != None)
922 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
923 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
924 XCopyArea(display, src_pixmap, d, tile_clip_gc,
925 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
930 printf("DrawGraphicThruMask(): tile '%d' needs clipping!\n", tile);
933 XSetClipOrigin(display, drawing_gc, dest_x-src_x, dest_y-src_y);
934 XCopyArea(display, src_pixmap, d, drawing_gc,
935 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
939 void DrawMiniGraphic(int x, int y, int graphic)
941 DrawMiniGraphicExt(drawto,gc, SX + x*MINI_TILEX, SY + y*MINI_TILEY, graphic);
942 MarkTileDirty(x/2, y/2);
945 void getMiniGraphicSource(int graphic, Pixmap *pixmap, int *x, int *y)
947 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
949 graphic -= GFX_START_ROCKSSCREEN;
950 *pixmap = pix[PIX_BACK];
951 *x = MINI_GFX_STARTX + (graphic % MINI_GFX_PER_LINE) * MINI_TILEX;
952 *y = MINI_GFX_STARTY + (graphic / MINI_GFX_PER_LINE) * MINI_TILEY;
954 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
956 graphic -= GFX_START_ROCKSMORE;
957 graphic -= ((graphic / MORE_PER_LINE) * MORE_PER_LINE) / 2;
958 *pixmap = pix[PIX_MORE];
959 *x = MINI_MORE_STARTX + (graphic % MINI_MORE_PER_LINE) * MINI_TILEX;
960 *y = MINI_MORE_STARTY + (graphic / MINI_MORE_PER_LINE) * MINI_TILEY;
962 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
964 graphic -= GFX_START_ROCKSFONT;
965 *pixmap = pix[PIX_SMALLFONT];
966 *x = (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE;
967 *y = ((graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE +
968 FC_SPECIAL2 * FONT2_YSIZE * FONT_LINES_PER_FONT);
972 *pixmap = pix[PIX_MORE];
973 *x = MINI_MORE_STARTX;
974 *y = MINI_MORE_STARTY;
978 void DrawMiniGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
986 getMiniGraphicSource(graphic, &pixmap, &src_x, &src_y);
987 XCopyArea(display, pixmap, d, gc,
988 src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
992 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
994 graphic -= GFX_START_ROCKSSCREEN;
995 XCopyArea(display, pix[PIX_BACK], d, gc,
996 MINI_GFX_STARTX + (graphic % MINI_GFX_PER_LINE) * MINI_TILEX,
997 MINI_GFX_STARTY + (graphic / MINI_GFX_PER_LINE) * MINI_TILEY,
998 MINI_TILEX, MINI_TILEY, x, y);
1000 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
1002 graphic -= GFX_START_ROCKSMORE;
1003 XCopyArea(display, pix[PIX_MORE], d, gc,
1004 MINI_MORE_STARTX + (graphic % MINI_MORE_PER_LINE) * MINI_TILEX,
1005 MINI_MORE_STARTY + (graphic / MINI_MORE_PER_LINE) * MINI_TILEY,
1006 MINI_TILEX, MINI_TILEY, x, y);
1008 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
1010 graphic -= GFX_START_ROCKSFONT;
1011 XCopyArea(display, pix[PIX_SMALLFONT], d, gc,
1012 (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE,
1013 (graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE +
1014 FC_SPECIAL2 * FONT2_YSIZE * FONT_LINES_PER_FONT,
1015 MINI_TILEX, MINI_TILEY, x, y);
1018 XFillRectangle(display, d, gc, x, y, MINI_TILEX, MINI_TILEY);
1024 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
1025 int cut_mode, int mask_mode)
1027 int width = TILEX, height = TILEY;
1029 int src_x, src_y, dest_x, dest_y;
1036 DrawGraphic(x, y, graphic);
1040 if (dx || dy) /* Verschiebung der Grafik? */
1042 if (x < BX1) /* Element kommt von links ins Bild */
1049 else if (x > BX2) /* Element kommt von rechts ins Bild */
1055 else if (x==BX1 && dx < 0) /* Element verläßt links das Bild */
1061 else if (x==BX2 && dx > 0) /* Element verläßt rechts das Bild */
1063 else if (dx) /* allg. Bewegung in x-Richtung */
1064 MarkTileDirty(x + SIGN(dx), y);
1066 if (y < BY1) /* Element kommt von oben ins Bild */
1068 if (cut_mode==CUT_BELOW) /* Element oberhalb des Bildes */
1076 else if (y > BY2) /* Element kommt von unten ins Bild */
1082 else if (y==BY1 && dy < 0) /* Element verläßt oben das Bild */
1088 else if (dy > 0 && cut_mode == CUT_ABOVE)
1090 if (y == BY2) /* Element unterhalb des Bildes */
1096 MarkTileDirty(x, y + 1);
1097 } /* Element verläßt unten das Bild */
1098 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1100 else if (dy) /* allg. Bewegung in y-Richtung */
1101 MarkTileDirty(x, y + SIGN(dy));
1104 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
1106 src_pixmap = pix[PIX_BACK];
1107 drawing_gc = clip_gc[PIX_BACK];
1108 graphic -= GFX_START_ROCKSSCREEN;
1109 src_x = SX + (graphic % GFX_PER_LINE) * TILEX + cx;
1110 src_y = SY + (graphic / GFX_PER_LINE) * TILEY + cy;
1112 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
1114 src_pixmap = pix[PIX_MORE];
1115 drawing_gc = clip_gc[PIX_MORE];
1116 graphic -= GFX_START_ROCKSMORE;
1117 src_x = (graphic % MORE_PER_LINE) * TILEX + cx;
1118 src_y = (graphic / MORE_PER_LINE) * TILEY + cy;
1120 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
1122 src_pixmap = pix[PIX_HEROES];
1123 drawing_gc = clip_gc[PIX_HEROES];
1124 graphic -= GFX_START_ROCKSHEROES;
1125 src_x = (graphic % HEROES_PER_LINE) * TILEX + cx;
1126 src_y = (graphic / HEROES_PER_LINE) * TILEY + cy;
1128 else /* big font graphics currently not allowed (and not needed) */
1131 dest_x = FX + x * TILEX + dx;
1132 dest_y = FY + y * TILEY + dy;
1135 if (!IN_SCR_FIELD(x,y))
1137 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1138 printf("DrawGraphicShifted(): This should never happen!\n");
1143 if (mask_mode == USE_MASKING)
1145 if (tile_clipmask[tile] != None)
1147 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
1148 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
1149 XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
1150 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
1155 printf("DrawGraphicShifted(): tile '%d' needs clipping!\n", tile);
1158 XSetClipOrigin(display, drawing_gc, dest_x - src_x, dest_y - src_y);
1159 XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
1160 src_x, src_y, width, height, dest_x, dest_y);
1164 XCopyArea(display, src_pixmap, drawto_field, gc,
1165 src_x, src_y, width, height, dest_x, dest_y);
1170 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
1173 DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, USE_MASKING);
1176 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1177 int cut_mode, int mask_mode)
1179 int ux = LEVELX(x), uy = LEVELY(y);
1180 int graphic = el2gfx(element);
1181 int phase8 = ABS(MovPos[ux][uy]) / (TILEX / 8);
1182 int phase4 = phase8 / 2;
1183 int phase2 = phase8 / 4;
1184 int dir = MovDir[ux][uy];
1186 if (element == EL_PACMAN || element == EL_KAEFER || element == EL_FLIEGER)
1188 graphic += 4 * !phase2;
1192 else if (dir == MV_LEFT)
1194 else if (dir == MV_DOWN)
1197 else if (element == EL_SP_SNIKSNAK)
1200 graphic = GFX_SP_SNIKSNAK_LEFT;
1201 else if (dir == MV_RIGHT)
1202 graphic = GFX_SP_SNIKSNAK_RIGHT;
1203 else if (dir == MV_UP)
1204 graphic = GFX_SP_SNIKSNAK_UP;
1206 graphic = GFX_SP_SNIKSNAK_DOWN;
1208 graphic += (phase8 < 4 ? phase8 : 7 - phase8);
1210 else if (element == EL_SP_ELECTRON)
1212 graphic = GFX2_SP_ELECTRON + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1214 else if (element == EL_MAULWURF || element == EL_PINGUIN ||
1215 element == EL_SCHWEIN || element == EL_DRACHE)
1218 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_LEFT :
1219 element == EL_PINGUIN ? GFX_PINGUIN_LEFT :
1220 element == EL_SCHWEIN ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
1221 else if (dir == MV_RIGHT)
1222 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_RIGHT :
1223 element == EL_PINGUIN ? GFX_PINGUIN_RIGHT :
1224 element == EL_SCHWEIN ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
1225 else if (dir == MV_UP)
1226 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_UP :
1227 element == EL_PINGUIN ? GFX_PINGUIN_UP :
1228 element == EL_SCHWEIN ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
1230 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_DOWN :
1231 element == EL_PINGUIN ? GFX_PINGUIN_DOWN :
1232 element == EL_SCHWEIN ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
1236 else if (element == EL_SONDE)
1238 graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1240 else if (element == EL_SALZSAEURE)
1242 graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_NORMAL);
1244 else if (element == EL_BUTTERFLY || element == EL_FIREFLY)
1248 else if ((element == EL_FELSBROCKEN || element == EL_SP_ZONK ||
1249 IS_GEM(element)) && !cut_mode)
1251 if (element == EL_FELSBROCKEN || element == EL_SP_ZONK)
1254 graphic += (4 - phase4) % 4;
1255 else if (dir == MV_RIGHT)
1258 graphic += phase2 * 2;
1260 else if (element != EL_SP_INFOTRON)
1264 if (element == EL_SP_ZONK)
1267 graphic += (4 - phase4) % 4;
1268 else if (dir == MV_RIGHT)
1271 graphic += phase2 * 2;
1273 else if (element != EL_SP_INFOTRON)
1274 graphic += phase2 * (element == EL_FELSBROCKEN ? 2 : 1);
1278 else if (element == EL_SIEB_LEER || element == EL_SIEB2_LEER ||
1279 element == EL_SIEB_VOLL || element == EL_SIEB2_VOLL)
1281 graphic += 3 + getGraphicAnimationPhase(4, 4, ANIM_REVERSE);
1283 else if (IS_AMOEBOID(element))
1285 graphic = (element == EL_AMOEBE_TOT ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
1286 graphic += (x + 2 * y + 4) % 4;
1288 else if (element == EL_MAUER_LEBT)
1290 boolean links_massiv = FALSE, rechts_massiv = FALSE;
1292 if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
1293 links_massiv = TRUE;
1294 if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
1295 rechts_massiv = TRUE;
1297 if (links_massiv && rechts_massiv)
1298 graphic = GFX_MAUERWERK;
1299 else if (links_massiv)
1300 graphic = GFX_MAUER_R;
1301 else if (rechts_massiv)
1302 graphic = GFX_MAUER_L;
1306 DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
1307 else if (mask_mode == USE_MASKING)
1308 DrawGraphicThruMask(x, y, graphic);
1310 DrawGraphic(x, y, graphic);
1313 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1314 int cut_mode, int mask_mode)
1316 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1317 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1318 cut_mode, mask_mode);
1321 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1324 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1327 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1330 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1333 void DrawScreenElementThruMask(int x, int y, int element)
1335 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1338 void DrawLevelElementThruMask(int x, int y, int element)
1340 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1343 void DrawLevelFieldThruMask(int x, int y)
1345 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1348 void ErdreichAnbroeckeln(int x, int y)
1350 int i, width, height, cx,cy;
1351 int ux = LEVELX(x), uy = LEVELY(y);
1352 int element, graphic;
1354 static int xy[4][2] =
1362 if (!IN_LEV_FIELD(ux, uy))
1365 element = Feld[ux][uy];
1367 if (element == EL_ERDREICH)
1369 if (!IN_SCR_FIELD(x, y))
1372 graphic = GFX_ERDENRAND;
1378 uxx = ux + xy[i][0];
1379 uyy = uy + xy[i][1];
1380 if (!IN_LEV_FIELD(uxx, uyy))
1383 element = Feld[uxx][uyy];
1385 if (element == EL_ERDREICH)
1388 if (i == 1 || i == 2)
1392 cx = (i == 2 ? TILEX - snip : 0);
1400 cy = (i == 3 ? TILEY - snip : 0);
1403 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1404 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1405 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1406 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1409 MarkTileDirty(x, y);
1413 graphic = GFX_ERDENRAND;
1417 int xx, yy, uxx, uyy;
1421 uxx = ux + xy[i][0];
1422 uyy = uy + xy[i][1];
1424 if (!IN_LEV_FIELD(uxx, uyy) || Feld[uxx][uyy] != EL_ERDREICH ||
1425 !IN_SCR_FIELD(xx, yy))
1428 if (i == 1 || i == 2)
1432 cx = (i == 1 ? TILEX - snip : 0);
1440 cy = (i==0 ? TILEY-snip : 0);
1443 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1444 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1445 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1446 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1448 MarkTileDirty(xx, yy);
1453 void DrawScreenElement(int x, int y, int element)
1455 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1456 ErdreichAnbroeckeln(x, y);
1459 void DrawLevelElement(int x, int y, int element)
1461 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1462 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1465 void DrawScreenField(int x, int y)
1467 int ux = LEVELX(x), uy = LEVELY(y);
1470 if (!IN_LEV_FIELD(ux, uy))
1472 if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
1473 element = EL_LEERRAUM;
1475 element = BorderElement;
1477 DrawScreenElement(x, y, element);
1481 element = Feld[ux][uy];
1483 if (IS_MOVING(ux, uy))
1485 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1486 boolean cut_mode = NO_CUTTING;
1488 if (Store[ux][uy] == EL_MORAST_LEER ||
1489 Store[ux][uy] == EL_SIEB_LEER ||
1490 Store[ux][uy] == EL_SIEB2_LEER ||
1491 Store[ux][uy] == EL_AMOEBE_NASS)
1492 cut_mode = CUT_ABOVE;
1493 else if (Store[ux][uy] == EL_MORAST_VOLL ||
1494 Store[ux][uy] == EL_SIEB_VOLL ||
1495 Store[ux][uy] == EL_SIEB2_VOLL)
1496 cut_mode = CUT_BELOW;
1498 if (cut_mode == CUT_ABOVE)
1499 DrawScreenElementShifted(x, y, 0, 0, Store[ux][uy], NO_CUTTING);
1501 DrawScreenElement(x, y, EL_LEERRAUM);
1504 DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1506 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1508 if (Store[ux][uy] == EL_SALZSAEURE)
1509 DrawLevelElementThruMask(ux, uy + 1, EL_SALZSAEURE);
1511 else if (IS_BLOCKED(ux, uy))
1516 boolean cut_mode = NO_CUTTING;
1518 Blocked2Moving(ux, uy, &oldx, &oldy);
1521 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1522 MovDir[oldx][oldy] == MV_RIGHT);
1524 if (Store[oldx][oldy] == EL_MORAST_LEER ||
1525 Store[oldx][oldy] == EL_SIEB_LEER ||
1526 Store[oldx][oldy] == EL_SIEB2_LEER ||
1527 Store[oldx][oldy] == EL_AMOEBE_NASS)
1528 cut_mode = CUT_ABOVE;
1530 DrawScreenElement(x, y, EL_LEERRAUM);
1531 element = Feld[oldx][oldy];
1534 DrawScreenElementShifted(sx,sy, MovPos[oldx][oldy],0,element,NO_CUTTING);
1536 DrawScreenElementShifted(sx,sy, 0,MovPos[oldx][oldy],element,cut_mode);
1538 else if (IS_DRAWABLE(element))
1539 DrawScreenElement(x, y, element);
1541 DrawScreenElement(x, y, EL_LEERRAUM);
1544 void DrawLevelField(int x, int y)
1546 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1547 DrawScreenField(SCREENX(x), SCREENY(y));
1548 else if (IS_MOVING(x, y))
1552 Moving2Blocked(x, y, &newx, &newy);
1553 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1554 DrawScreenField(SCREENX(newx), SCREENY(newy));
1556 else if (IS_BLOCKED(x, y))
1560 Blocked2Moving(x, y, &oldx, &oldy);
1561 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1562 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1566 void DrawMiniElement(int x, int y, int element)
1572 DrawMiniGraphic(x, y, -1);
1576 graphic = el2gfx(element);
1577 DrawMiniGraphic(x, y, graphic);
1580 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1582 int x = sx + scroll_x, y = sy + scroll_y;
1584 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1585 DrawMiniElement(sx, sy, EL_LEERRAUM);
1586 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1587 DrawMiniElement(sx, sy, Feld[x][y]);
1590 int steel_type, steel_position;
1593 { GFX_VSTEEL_UPPER_LEFT, GFX_ISTEEL_UPPER_LEFT },
1594 { GFX_VSTEEL_UPPER_RIGHT, GFX_ISTEEL_UPPER_RIGHT },
1595 { GFX_VSTEEL_LOWER_LEFT, GFX_ISTEEL_LOWER_LEFT },
1596 { GFX_VSTEEL_LOWER_RIGHT, GFX_ISTEEL_LOWER_RIGHT },
1597 { GFX_VSTEEL_VERTICAL, GFX_ISTEEL_VERTICAL },
1598 { GFX_VSTEEL_HORIZONTAL, GFX_ISTEEL_HORIZONTAL }
1601 steel_type = (BorderElement == EL_BETON ? 0 : 1);
1602 steel_position = (x == -1 && y == -1 ? 0 :
1603 x == lev_fieldx && y == -1 ? 1 :
1604 x == -1 && y == lev_fieldy ? 2 :
1605 x == lev_fieldx && y == lev_fieldy ? 3 :
1606 x == -1 || x == lev_fieldx ? 4 :
1607 y == -1 || y == lev_fieldy ? 5 : -1);
1609 if (steel_position != -1)
1610 DrawMiniGraphic(sx, sy, border[steel_position][steel_type]);
1614 if (x == -1 && y == -1)
1615 DrawMiniGraphic(sx, sy, GFX_STEEL_UPPER_LEFT);
1616 else if (x == lev_fieldx && y == -1)
1617 DrawMiniGraphic(sx, sy, GFX_STEEL_UPPER_RIGHT);
1618 else if (x == -1 && y == lev_fieldy)
1619 DrawMiniGraphic(sx, sy, GFX_STEEL_LOWER_LEFT);
1620 else if (x == lev_fieldx && y == lev_fieldy)
1621 DrawMiniGraphic(sx, sy, GFX_STEEL_LOWER_RIGHT);
1622 else if (x == -1 || x == lev_fieldx)
1623 DrawMiniGraphic(sx, sy, GFX_STEEL_VERTICAL);
1624 else if (y == -1 || y == lev_fieldy)
1625 DrawMiniGraphic(sx, sy, GFX_STEEL_HORIZONTAL);
1632 void DrawMicroElement(int xpos, int ypos, int element)
1636 if (element == EL_LEERRAUM)
1639 graphic = el2gfx(element);
1641 if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
1643 graphic -= GFX_START_ROCKSMORE;
1644 graphic -= ((graphic / MORE_PER_LINE) * MORE_PER_LINE) / 2;
1645 XCopyArea(display, pix[PIX_MORE], drawto, gc,
1646 MICRO_MORE_STARTX + (graphic % MICRO_MORE_PER_LINE) *MICRO_TILEX,
1647 MICRO_MORE_STARTY + (graphic / MICRO_MORE_PER_LINE) *MICRO_TILEY,
1648 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1651 XCopyArea(display, pix[PIX_BACK], drawto, gc,
1652 MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX,
1653 MICRO_GFX_STARTY + (graphic / MICRO_GFX_PER_LINE) * MICRO_TILEY,
1654 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1663 for(x=BX1; x<=BX2; x++)
1664 for(y=BY1; y<=BY2; y++)
1665 DrawScreenField(x, y);
1667 if (setup.soft_scrolling)
1668 XCopyArea(display, fieldbuffer, backbuffer, gc,
1669 FX, FY, SXSIZE, SYSIZE, SX, SY);
1671 redraw_mask |= (REDRAW_FIELD | REDRAW_FROM_BACKBUFFER);
1674 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1678 for(x=0; x<size_x; x++)
1679 for(y=0; y<size_y; y++)
1680 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1682 redraw_mask |= REDRAW_FIELD;
1685 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1689 /* determine border element for this level */
1692 XFillRectangle(display, drawto, gc,
1693 xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
1695 if (lev_fieldx < STD_LEV_FIELDX)
1696 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1697 if (lev_fieldy < STD_LEV_FIELDY)
1698 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1700 xpos += MICRO_TILEX;
1701 ypos += MICRO_TILEY;
1703 for(x=-1; x<=STD_LEV_FIELDX; x++)
1705 for(y=-1; y<=STD_LEV_FIELDY; y++)
1707 int lx = from_x + x, ly = from_y + y;
1709 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1710 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1712 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1)
1713 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1718 redraw_mask |= REDRAW_MICROLEVEL;
1721 static void DrawMicroLevelLabelExt(int mode)
1723 char label_text[100];
1725 XFillRectangle(display, drawto,gc,
1726 SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
1728 strcpy(label_text, (mode == 1 ? level.name :
1729 mode == 2 ? "created by" :
1730 mode == 3 ? level.author : ""));
1732 if (strlen(label_text) > 0)
1734 int size, lxpos, lypos;
1736 label_text[SXSIZE / FONT4_XSIZE] = '\0';
1738 size = strlen(label_text);
1739 lxpos = SX + (SXSIZE - size * FONT4_XSIZE) / 2;
1740 lypos = MICROLABEL_YPOS;
1742 DrawText(lxpos, lypos, label_text, FS_SMALL, FC_SPECIAL2);
1745 redraw_mask |= REDRAW_MICROLEVEL;
1748 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1750 static unsigned long scroll_delay = 0;
1751 static unsigned long label_delay = 0;
1752 static int from_x, from_y, scroll_direction;
1753 static int label_state, label_counter;
1757 from_x = from_y = 0;
1758 scroll_direction = MV_RIGHT;
1762 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1763 DrawMicroLevelLabelExt(label_state);
1765 /* initialize delay counters */
1766 DelayReached(&scroll_delay, 0);
1767 DelayReached(&label_delay, 0);
1772 /* scroll micro level, if needed */
1773 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1774 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1776 switch (scroll_direction)
1782 scroll_direction = MV_UP;
1786 if (from_x < lev_fieldx - STD_LEV_FIELDX)
1789 scroll_direction = MV_DOWN;
1796 scroll_direction = MV_RIGHT;
1800 if (from_y < lev_fieldy - STD_LEV_FIELDY)
1803 scroll_direction = MV_LEFT;
1810 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1813 /* redraw micro level label, if needed */
1814 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1815 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1816 strcmp(level.author, leveldir[leveldir_nr].name) != 0 &&
1817 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1819 label_counter = (label_counter + 1) % 23;
1820 label_state = (label_counter >= 0 && label_counter <= 7 ? 1 :
1821 label_counter >= 9 && label_counter <= 12 ? 2 :
1822 label_counter >= 14 && label_counter <= 21 ? 3 : 0);
1823 DrawMicroLevelLabelExt(label_state);
1827 int REQ_in_range(int x, int y)
1829 if (y > DY+249 && y < DY+278)
1831 if (x > DX+1 && x < DX+48)
1833 else if (x > DX+51 && x < DX+98)
1839 boolean Request(char *text, unsigned int req_state)
1841 int mx, my, ty, result = -1;
1842 unsigned int old_door_state;
1845 /* pause network game while waiting for request to answer */
1846 if (options.network &&
1847 game_status == PLAYING &&
1848 req_state & REQUEST_WAIT_FOR)
1849 SendToServer_PausePlaying();
1852 old_door_state = GetDoorState();
1856 CloseDoor(DOOR_CLOSE_1);
1858 /* save old door content */
1859 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1860 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
1861 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
1863 /* clear door drawing field */
1864 XFillRectangle(display, drawto, gc, DX, DY, DXSIZE, DYSIZE);
1866 /* write text for request */
1867 for(ty=0; ty<13; ty++)
1875 for(tl=0,tx=0; tx<7; tl++,tx++)
1878 if (!tc || tc == 32)
1889 DrawTextExt(drawto, gc,
1890 DX + 51 - (tl * 14)/2, DY + 8 + ty * 16,
1891 txt, FS_SMALL, FC_YELLOW);
1892 text += tl + (tc == 32 ? 1 : 0);
1895 if (req_state & REQ_ASK)
1897 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
1898 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
1900 else if (req_state & REQ_CONFIRM)
1902 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
1904 else if (req_state & REQ_PLAYER)
1906 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
1907 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
1908 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
1909 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
1912 /* copy request gadgets to door backbuffer */
1913 XCopyArea(display, drawto, pix[PIX_DB_DOOR], gc,
1914 DX, DY, DXSIZE, DYSIZE,
1915 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1917 OpenDoor(DOOR_OPEN_1);
1920 if (!(req_state & REQUEST_WAIT_FOR))
1923 if (game_status != MAINMENU)
1926 button_status = MB_RELEASED;
1928 request_gadget_id = -1;
1932 if (XPending(display))
1936 XNextEvent(display, &event);
1944 if (event.type == MotionNotify)
1951 if (!XQueryPointer(display, window, &root, &child,
1952 &root_x, &root_y, &win_x, &win_y, &mask))
1958 motion_status = TRUE;
1959 mx = ((XMotionEvent *) &event)->x;
1960 my = ((XMotionEvent *) &event)->y;
1964 motion_status = FALSE;
1965 mx = ((XButtonEvent *) &event)->x;
1966 my = ((XButtonEvent *) &event)->y;
1967 if (event.type==ButtonPress)
1968 button_status = ((XButtonEvent *) &event)->button;
1970 button_status = MB_RELEASED;
1973 /* this sets 'request_gadget_id' */
1974 HandleGadgets(mx, my, button_status);
1976 switch(request_gadget_id)
1978 case TOOL_CTRL_ID_YES:
1981 case TOOL_CTRL_ID_NO:
1984 case TOOL_CTRL_ID_CONFIRM:
1985 result = TRUE | FALSE;
1988 case TOOL_CTRL_ID_PLAYER_1:
1991 case TOOL_CTRL_ID_PLAYER_2:
1994 case TOOL_CTRL_ID_PLAYER_3:
1997 case TOOL_CTRL_ID_PLAYER_4:
2009 switch(XLookupKeysym((XKeyEvent *)&event,
2010 ((XKeyEvent *)&event)->state))
2023 if (req_state & REQ_PLAYER)
2028 key_joystick_mapping = 0;
2032 HandleOtherEvents(&event);
2036 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2038 int joy = AnyJoystick();
2040 if (joy & JOY_BUTTON_1)
2042 else if (joy & JOY_BUTTON_2)
2048 /* don't eat all CPU time */
2052 if (game_status != MAINMENU)
2057 if (!(req_state & REQ_STAY_OPEN))
2059 CloseDoor(DOOR_CLOSE_1);
2061 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
2063 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
2064 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
2065 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
2066 OpenDoor(DOOR_OPEN_1);
2073 /* continue network game after request */
2074 if (options.network &&
2075 game_status == PLAYING &&
2076 req_state & REQUEST_WAIT_FOR)
2077 SendToServer_ContinuePlaying();
2083 unsigned int OpenDoor(unsigned int door_state)
2085 unsigned int new_door_state;
2087 if (door_state & DOOR_COPY_BACK)
2089 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
2090 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
2091 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2092 door_state &= ~DOOR_COPY_BACK;
2095 new_door_state = MoveDoor(door_state);
2097 return(new_door_state);
2100 unsigned int CloseDoor(unsigned int door_state)
2102 unsigned int new_door_state;
2104 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
2105 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2106 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
2107 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2109 new_door_state = MoveDoor(door_state);
2111 return(new_door_state);
2114 unsigned int GetDoorState()
2116 return(MoveDoor(DOOR_GET_STATE));
2119 unsigned int MoveDoor(unsigned int door_state)
2121 static int door1 = DOOR_OPEN_1;
2122 static int door2 = DOOR_CLOSE_2;
2123 static unsigned long door_delay = 0;
2124 int x, start, stepsize = 2;
2125 unsigned long door_delay_value = stepsize * 5;
2127 if (door_state == DOOR_GET_STATE)
2128 return(door1 | door2);
2130 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2131 door_state &= ~DOOR_OPEN_1;
2132 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2133 door_state &= ~DOOR_CLOSE_1;
2134 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2135 door_state &= ~DOOR_OPEN_2;
2136 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2137 door_state &= ~DOOR_CLOSE_2;
2139 if (setup.quick_doors)
2142 door_delay_value = 0;
2143 StopSound(SND_OEFFNEN);
2146 if (door_state & DOOR_ACTION)
2148 if (!(door_state & DOOR_NO_DELAY))
2149 PlaySoundStereo(SND_OEFFNEN, PSND_MAX_RIGHT);
2151 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2153 for(x=start; x<=DXSIZE; x+=stepsize)
2155 WaitUntilDelayReached(&door_delay, door_delay_value);
2157 if (door_state & DOOR_ACTION_1)
2159 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
2160 int j = (DXSIZE - i) / 3;
2162 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
2163 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
2164 DXSIZE,DYSIZE - i/2, DX, DY);
2166 XFillRectangle(display, drawto, gc, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
2168 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2169 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2170 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
2171 DXSIZE, DOOR_GFX_PAGEY1, i, 77, DX + DXSIZE - i, DY + j);
2172 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2173 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63, DX + DXSIZE - i,
2175 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2176 DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
2177 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2178 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j, DX, DY);
2179 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2180 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63, DX, DY + 140 - j);
2182 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2183 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2185 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2186 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2188 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2189 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2190 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2191 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2192 DX + DXSIZE - i, DY + 77 + j);
2193 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2194 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2195 DX + DXSIZE - i, DY + 203 + j);
2197 redraw_mask |= REDRAW_DOOR_1;
2200 if (door_state & DOOR_ACTION_2)
2202 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
2203 int j = (VXSIZE - i) / 3;
2205 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
2206 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
2207 VXSIZE, VYSIZE - i/2, VX, VY);
2209 XFillRectangle(display, drawto, gc, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
2211 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2212 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2213 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2214 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2, VX + VXSIZE-i, VY+j);
2215 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2216 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2217 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
2218 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j, VX, VY);
2220 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2221 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2,
2222 VX, VY + VYSIZE / 2 - j);
2223 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2224 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2225 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2226 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2 - j,
2227 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2229 redraw_mask |= REDRAW_DOOR_2;
2237 XCopyArea(display, drawto, window, gc, DX, DY, DXSIZE, DYSIZE, DX, DY);
2242 if (game_status == MAINMENU)
2247 if (setup.quick_doors)
2248 StopSound(SND_OEFFNEN);
2250 if (door_state & DOOR_ACTION_1)
2251 door1 = door_state & DOOR_ACTION_1;
2252 if (door_state & DOOR_ACTION_2)
2253 door2 = door_state & DOOR_ACTION_2;
2255 return(door1 | door2);
2258 int ReadPixel(Drawable d, int x, int y)
2260 XImage *pixel_image;
2261 unsigned long pixel_value;
2263 pixel_image = XGetImage(display, d, x, y, 1, 1, AllPlanes, ZPixmap);
2264 pixel_value = XGetPixel(pixel_image, 0, 0);
2266 XDestroyImage(pixel_image);
2271 /* ---------- new tool button stuff ---------------------------------------- */
2273 /* graphic position values for tool buttons */
2274 #define TOOL_BUTTON_YES_XPOS 2
2275 #define TOOL_BUTTON_YES_YPOS 250
2276 #define TOOL_BUTTON_YES_GFX_YPOS 0
2277 #define TOOL_BUTTON_YES_XSIZE 46
2278 #define TOOL_BUTTON_YES_YSIZE 28
2279 #define TOOL_BUTTON_NO_XPOS 52
2280 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2281 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2282 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2283 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2284 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2285 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2286 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2287 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2288 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2289 #define TOOL_BUTTON_PLAYER_XSIZE 30
2290 #define TOOL_BUTTON_PLAYER_YSIZE 30
2291 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2292 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2293 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2294 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2295 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2296 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2297 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2298 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2299 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2300 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2301 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2302 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2303 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2304 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2305 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2306 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2307 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2308 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2309 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2310 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2319 } toolbutton_info[NUM_TOOL_BUTTONS] =
2322 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2323 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2324 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2329 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2330 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2331 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2336 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2337 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2338 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2339 TOOL_CTRL_ID_CONFIRM,
2343 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2344 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2345 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2346 TOOL_CTRL_ID_PLAYER_1,
2350 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2351 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2352 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2353 TOOL_CTRL_ID_PLAYER_2,
2357 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2358 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2359 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2360 TOOL_CTRL_ID_PLAYER_3,
2364 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2365 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2366 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2367 TOOL_CTRL_ID_PLAYER_4,
2372 void CreateToolButtons()
2376 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2378 Pixmap gd_pixmap = pix[PIX_DOOR];
2379 Pixmap deco_pixmap = None;
2380 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2381 struct GadgetInfo *gi;
2382 unsigned long event_mask;
2383 int gd_xoffset, gd_yoffset;
2384 int gd_x1, gd_x2, gd_y;
2387 event_mask = GD_EVENT_RELEASED;
2389 gd_xoffset = toolbutton_info[i].xpos;
2390 gd_yoffset = toolbutton_info[i].ypos;
2391 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2392 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2393 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2395 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2397 getMiniGraphicSource(GFX_SPIELER1 + id - TOOL_CTRL_ID_PLAYER_1,
2398 &deco_pixmap, &deco_x, &deco_y);
2399 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2400 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2403 gi = CreateGadget(GDI_CUSTOM_ID, id,
2404 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2405 GDI_X, DX + toolbutton_info[i].x,
2406 GDI_Y, DY + toolbutton_info[i].y,
2407 GDI_WIDTH, toolbutton_info[i].width,
2408 GDI_HEIGHT, toolbutton_info[i].height,
2409 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2410 GDI_STATE, GD_BUTTON_UNPRESSED,
2411 GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y,
2412 GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y,
2413 GDI_DECORATION_DESIGN, deco_pixmap, deco_x, deco_y,
2414 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2415 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2416 GDI_DECORATION_SHIFTING, 1, 1,
2417 GDI_EVENT_MASK, event_mask,
2418 GDI_CALLBACK_ACTION, HandleToolButtons,
2422 Error(ERR_EXIT, "cannot create gadget");
2424 tool_gadget[id] = gi;
2428 static void UnmapToolButtons()
2432 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2433 UnmapGadget(tool_gadget[i]);
2436 static void HandleToolButtons(struct GadgetInfo *gi)
2438 request_gadget_id = gi->custom_id;
2442 int id = gi->custom_id;
2444 if (game_status != PLAYING)
2449 case GAME_CTRL_ID_STOP:
2452 CloseDoor(DOOR_CLOSE_1);
2453 game_status = MAINMENU;
2458 if (Request("Do you really want to quit the game ?",
2459 REQ_ASK | REQ_STAY_CLOSED))
2462 if (options.network)
2463 SendToServer_StopPlaying();
2467 game_status = MAINMENU;
2472 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
2475 case GAME_CTRL_ID_PAUSE:
2476 if (options.network)
2480 SendToServer_ContinuePlaying();
2482 SendToServer_PausePlaying();
2489 case GAME_CTRL_ID_PLAY:
2493 if (options.network)
2494 SendToServer_ContinuePlaying();
2498 tape.pausing = FALSE;
2499 DrawVideoDisplay(VIDEO_STATE_PAUSE_OFF,0);
2504 case SOUND_CTRL_ID_MUSIC:
2505 if (setup.sound_music)
2507 setup.sound_music = FALSE;
2508 FadeSound(background_loop[level_nr % num_bg_loops]);
2510 else if (sound_loops_allowed)
2512 setup.sound = setup.sound_music = TRUE;
2513 PlaySoundLoop(background_loop[level_nr % num_bg_loops]);
2517 case SOUND_CTRL_ID_LOOPS:
2518 if (setup.sound_loops)
2519 setup.sound_loops = FALSE;
2520 else if (sound_loops_allowed)
2521 setup.sound = setup.sound_loops = TRUE;
2524 case SOUND_CTRL_ID_SIMPLE:
2525 if (setup.sound_simple)
2526 setup.sound_simple = FALSE;
2527 else if (sound_status==SOUND_AVAILABLE)
2528 setup.sound = setup.sound_simple = TRUE;
2540 int el2gfx(int element)
2544 case EL_LEERRAUM: return -1;
2545 case EL_ERDREICH: return GFX_ERDREICH;
2546 case EL_MAUERWERK: return GFX_MAUERWERK;
2547 case EL_FELSBODEN: return GFX_FELSBODEN;
2548 case EL_FELSBROCKEN: return GFX_FELSBROCKEN;
2549 case EL_SCHLUESSEL: return GFX_SCHLUESSEL;
2550 case EL_EDELSTEIN: return GFX_EDELSTEIN;
2551 case EL_AUSGANG_ZU: return GFX_AUSGANG_ZU;
2552 case EL_AUSGANG_ACT: return GFX_AUSGANG_ACT;
2553 case EL_AUSGANG_AUF: return GFX_AUSGANG_AUF;
2554 case EL_SPIELFIGUR: return GFX_SPIELFIGUR;
2555 case EL_SPIELER1: return GFX_SPIELER1;
2556 case EL_SPIELER2: return GFX_SPIELER2;
2557 case EL_SPIELER3: return GFX_SPIELER3;
2558 case EL_SPIELER4: return GFX_SPIELER4;
2559 case EL_KAEFER: return GFX_KAEFER;
2560 case EL_KAEFER_R: return GFX_KAEFER_R;
2561 case EL_KAEFER_O: return GFX_KAEFER_O;
2562 case EL_KAEFER_L: return GFX_KAEFER_L;
2563 case EL_KAEFER_U: return GFX_KAEFER_U;
2564 case EL_FLIEGER: return GFX_FLIEGER;
2565 case EL_FLIEGER_R: return GFX_FLIEGER_R;
2566 case EL_FLIEGER_O: return GFX_FLIEGER_O;
2567 case EL_FLIEGER_L: return GFX_FLIEGER_L;
2568 case EL_FLIEGER_U: return GFX_FLIEGER_U;
2569 case EL_BUTTERFLY: return GFX_BUTTERFLY;
2570 case EL_BUTTERFLY_R: return GFX_BUTTERFLY_R;
2571 case EL_BUTTERFLY_O: return GFX_BUTTERFLY_O;
2572 case EL_BUTTERFLY_L: return GFX_BUTTERFLY_L;
2573 case EL_BUTTERFLY_U: return GFX_BUTTERFLY_U;
2574 case EL_FIREFLY: return GFX_FIREFLY;
2575 case EL_FIREFLY_R: return GFX_FIREFLY_R;
2576 case EL_FIREFLY_O: return GFX_FIREFLY_O;
2577 case EL_FIREFLY_L: return GFX_FIREFLY_L;
2578 case EL_FIREFLY_U: return GFX_FIREFLY_U;
2579 case EL_MAMPFER: return GFX_MAMPFER;
2580 case EL_ROBOT: return GFX_ROBOT;
2581 case EL_BETON: return GFX_BETON;
2582 case EL_DIAMANT: return GFX_DIAMANT;
2583 case EL_MORAST_LEER: return GFX_MORAST_LEER;
2584 case EL_MORAST_VOLL: return GFX_MORAST_VOLL;
2585 case EL_TROPFEN: return GFX_TROPFEN;
2586 case EL_BOMBE: return GFX_BOMBE;
2587 case EL_SIEB_INAKTIV: return GFX_SIEB_INAKTIV;
2588 case EL_SIEB_LEER: return GFX_SIEB_LEER;
2589 case EL_SIEB_VOLL: return GFX_SIEB_VOLL;
2590 case EL_SIEB_TOT: return GFX_SIEB_TOT;
2591 case EL_SALZSAEURE: return GFX_SALZSAEURE;
2592 case EL_AMOEBE_TOT: return GFX_AMOEBE_TOT;
2593 case EL_AMOEBE_NASS: return GFX_AMOEBE_NASS;
2594 case EL_AMOEBE_NORM: return GFX_AMOEBE_NORM;
2595 case EL_AMOEBE_VOLL: return GFX_AMOEBE_VOLL;
2596 case EL_AMOEBE_BD: return GFX_AMOEBE_BD;
2597 case EL_AMOEBA2DIAM: return GFX_AMOEBA2DIAM;
2598 case EL_KOKOSNUSS: return GFX_KOKOSNUSS;
2599 case EL_LIFE: return GFX_LIFE;
2600 case EL_LIFE_ASYNC: return GFX_LIFE_ASYNC;
2601 case EL_DYNAMIT: return GFX_DYNAMIT;
2602 case EL_BADEWANNE: return GFX_BADEWANNE;
2603 case EL_BADEWANNE1: return GFX_BADEWANNE1;
2604 case EL_BADEWANNE2: return GFX_BADEWANNE2;
2605 case EL_BADEWANNE3: return GFX_BADEWANNE3;
2606 case EL_BADEWANNE4: return GFX_BADEWANNE4;
2607 case EL_BADEWANNE5: return GFX_BADEWANNE5;
2608 case EL_ABLENK_AUS: return GFX_ABLENK_AUS;
2609 case EL_ABLENK_EIN: return GFX_ABLENK_EIN;
2610 case EL_SCHLUESSEL1: return GFX_SCHLUESSEL1;
2611 case EL_SCHLUESSEL2: return GFX_SCHLUESSEL2;
2612 case EL_SCHLUESSEL3: return GFX_SCHLUESSEL3;
2613 case EL_SCHLUESSEL4: return GFX_SCHLUESSEL4;
2614 case EL_PFORTE1: return GFX_PFORTE1;
2615 case EL_PFORTE2: return GFX_PFORTE2;
2616 case EL_PFORTE3: return GFX_PFORTE3;
2617 case EL_PFORTE4: return GFX_PFORTE4;
2618 case EL_PFORTE1X: return GFX_PFORTE1X;
2619 case EL_PFORTE2X: return GFX_PFORTE2X;
2620 case EL_PFORTE3X: return GFX_PFORTE3X;
2621 case EL_PFORTE4X: return GFX_PFORTE4X;
2622 case EL_DYNAMIT_AUS: return GFX_DYNAMIT_AUS;
2623 case EL_PACMAN: return GFX_PACMAN;
2624 case EL_PACMAN_R: return GFX_PACMAN_R;
2625 case EL_PACMAN_O: return GFX_PACMAN_O;
2626 case EL_PACMAN_L: return GFX_PACMAN_L;
2627 case EL_PACMAN_U: return GFX_PACMAN_U;
2628 case EL_UNSICHTBAR: return GFX_UNSICHTBAR;
2629 case EL_ERZ_EDEL: return GFX_ERZ_EDEL;
2630 case EL_ERZ_DIAM: return GFX_ERZ_DIAM;
2631 case EL_BIRNE_AUS: return GFX_BIRNE_AUS;
2632 case EL_BIRNE_EIN: return GFX_BIRNE_EIN;
2633 case EL_ZEIT_VOLL: return GFX_ZEIT_VOLL;
2634 case EL_ZEIT_LEER: return GFX_ZEIT_LEER;
2635 case EL_MAUER_LEBT: return GFX_MAUER_LEBT;
2636 case EL_MAUER_X: return GFX_MAUER_X;
2637 case EL_MAUER_Y: return GFX_MAUER_Y;
2638 case EL_MAUER_XY: return GFX_MAUER_XY;
2639 case EL_EDELSTEIN_BD: return GFX_EDELSTEIN_BD;
2640 case EL_EDELSTEIN_GELB: return GFX_EDELSTEIN_GELB;
2641 case EL_EDELSTEIN_ROT: return GFX_EDELSTEIN_ROT;
2642 case EL_EDELSTEIN_LILA: return GFX_EDELSTEIN_LILA;
2643 case EL_ERZ_EDEL_BD: return GFX_ERZ_EDEL_BD;
2644 case EL_ERZ_EDEL_GELB: return GFX_ERZ_EDEL_GELB;
2645 case EL_ERZ_EDEL_ROT: return GFX_ERZ_EDEL_ROT;
2646 case EL_ERZ_EDEL_LILA: return GFX_ERZ_EDEL_LILA;
2647 case EL_MAMPFER2: return GFX_MAMPFER2;
2648 case EL_SIEB2_INAKTIV: return GFX_SIEB2_INAKTIV;
2649 case EL_SIEB2_LEER: return GFX_SIEB2_LEER;
2650 case EL_SIEB2_VOLL: return GFX_SIEB2_VOLL;
2651 case EL_SIEB2_TOT: return GFX_SIEB2_TOT;
2652 case EL_DYNABOMB: return GFX_DYNABOMB;
2653 case EL_DYNABOMB_NR: return GFX_DYNABOMB_NR;
2654 case EL_DYNABOMB_SZ: return GFX_DYNABOMB_SZ;
2655 case EL_DYNABOMB_XL: return GFX_DYNABOMB_XL;
2656 case EL_SOKOBAN_OBJEKT: return GFX_SOKOBAN_OBJEKT;
2657 case EL_SOKOBAN_FELD_LEER: return GFX_SOKOBAN_FELD_LEER;
2658 case EL_SOKOBAN_FELD_VOLL: return GFX_SOKOBAN_FELD_VOLL;
2659 case EL_MAULWURF: return GFX_MAULWURF;
2660 case EL_PINGUIN: return GFX_PINGUIN;
2661 case EL_SCHWEIN: return GFX_SCHWEIN;
2662 case EL_DRACHE: return GFX_DRACHE;
2663 case EL_SONDE: return GFX_SONDE;
2664 case EL_PFEIL_L: return GFX_PFEIL_L;
2665 case EL_PFEIL_R: return GFX_PFEIL_R;
2666 case EL_PFEIL_O: return GFX_PFEIL_O;
2667 case EL_PFEIL_U: return GFX_PFEIL_U;
2668 case EL_SPEED_PILL: return GFX_SPEED_PILL;
2669 case EL_SP_TERMINAL_ACTIVE: return GFX_SP_TERMINAL;
2670 case EL_SP_BUG_ACTIVE: return GFX_SP_BUG_ACTIVE;
2671 case EL_SP_ZONK: return GFX_SP_ZONK;
2672 /* ^^^^^^^^^^ non-standard position in supaplex graphic set! */
2673 case EL_INVISIBLE_STEEL: return GFX_INVISIBLE_STEEL;
2674 case EL_BLACK_ORB: return GFX_BLACK_ORB;
2675 case EL_EM_GATE_1: return GFX_EM_GATE_1;
2676 case EL_EM_GATE_2: return GFX_EM_GATE_2;
2677 case EL_EM_GATE_3: return GFX_EM_GATE_3;
2678 case EL_EM_GATE_4: return GFX_EM_GATE_4;
2679 case EL_EM_GATE_1X: return GFX_EM_GATE_1X;
2680 case EL_EM_GATE_2X: return GFX_EM_GATE_2X;
2681 case EL_EM_GATE_3X: return GFX_EM_GATE_3X;
2682 case EL_EM_GATE_4X: return GFX_EM_GATE_4X;
2683 case EL_EM_KEY_1_FILE: return GFX_EM_KEY_1;
2684 case EL_EM_KEY_2_FILE: return GFX_EM_KEY_2;
2685 case EL_EM_KEY_3_FILE: return GFX_EM_KEY_3;
2686 case EL_EM_KEY_4_FILE: return GFX_EM_KEY_4;
2687 case EL_EM_KEY_1: return GFX_EM_KEY_1;
2688 case EL_EM_KEY_2: return GFX_EM_KEY_2;
2689 case EL_EM_KEY_3: return GFX_EM_KEY_3;
2690 case EL_EM_KEY_4: return GFX_EM_KEY_4;
2694 if (IS_CHAR(element))
2695 return GFX_CHAR_START + (element - EL_CHAR_START);
2696 else if (element >= EL_SP_START && element <= EL_SP_END)
2698 int nr_element = element - EL_SP_START;
2699 int gfx_per_line = 8;
2701 (nr_element / gfx_per_line) * MORE_PER_LINE +
2702 (nr_element % gfx_per_line);
2704 return GFX_START_ROCKSMORE + nr_graphic;