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 void UnmapToolButtons();
47 static void HandleToolButtons(struct GadgetInfo *);
49 static struct GadgetInfo *tool_gadget[NUM_TOOL_BUTTONS];
50 static int request_gadget_id = -1;
52 void SetDrawtoField(int mode)
54 if (mode == DRAW_BUFFERED && setup.soft_scrolling)
65 drawto_field = fieldbuffer;
67 else /* DRAW_DIRECT, DRAW_BACKBUFFER */
78 drawto_field = (mode == DRAW_DIRECT ? window : backbuffer);
85 Drawable buffer = (drawto_field == window ? backbuffer : drawto_field);
87 if (setup.direct_draw && game_status == PLAYING)
88 redraw_mask &= ~REDRAW_MAIN;
90 if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD)
91 redraw_mask |= REDRAW_FIELD;
93 if (redraw_mask & REDRAW_FIELD)
94 redraw_mask &= ~REDRAW_TILES;
97 if (redraw_mask & REDRAW_FIELD ||
98 (ScreenGfxPos && setup.soft_scrolling && game_status == PLAYING))
99 redraw_mask &= ~REDRAW_TILES;
105 /* synchronize X11 graphics at this point; if we would synchronize the
106 display immediately after the buffer switching (after the XFlush),
107 this could mean that we have to wait for the graphics to complete,
108 although we could go on doing calculations for the next frame */
110 XSync(display, FALSE);
114 wait_for_vsync = TRUE;
118 if (redraw_mask & REDRAW_ALL)
120 XCopyArea(display, backbuffer, window, gc,
121 0, 0, WIN_XSIZE, WIN_YSIZE,
126 if (redraw_mask & REDRAW_FIELD)
128 if (game_status != PLAYING || redraw_mask & REDRAW_FROM_BACKBUFFER)
130 XCopyArea(display, backbuffer, window, gc,
131 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
136 int fx = FX, fy = FY;
138 if (setup.soft_scrolling)
140 fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
141 fy += (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
144 if (setup.soft_scrolling ||
145 ABS(ScreenMovPos) + ScrollStepSize == TILEX ||
146 ABS(ScreenMovPos) == ScrollStepSize ||
147 redraw_tiles > REDRAWTILES_THRESHOLD)
149 XCopyArea(display, buffer, window, gc, fx, fy, SXSIZE, SYSIZE, SX, SY);
153 printf("redrawing all (ScreenGfxPos == %d) because %s\n",
155 (setup.soft_scrolling ?
156 "setup.soft_scrolling" :
157 ABS(ScreenGfxPos) + ScrollStepSize == TILEX ?
158 "ABS(ScreenGfxPos) + ScrollStepSize == TILEX" :
159 ABS(ScreenGfxPos) == ScrollStepSize ?
160 "ABS(ScreenGfxPos) == ScrollStepSize" :
161 "redraw_tiles > REDRAWTILES_THRESHOLD"));
166 redraw_mask &= ~REDRAW_MAIN;
169 if (redraw_mask & REDRAW_DOORS)
171 if (redraw_mask & REDRAW_DOOR_1)
172 XCopyArea(display, backbuffer, window, gc,
173 DX, DY, DXSIZE, DYSIZE,
175 if (redraw_mask & REDRAW_DOOR_2)
177 if ((redraw_mask & REDRAW_DOOR_2) == REDRAW_DOOR_2)
178 XCopyArea(display,backbuffer,window,gc,
179 VX,VY, VXSIZE,VYSIZE,
183 if (redraw_mask & REDRAW_VIDEO_1)
184 XCopyArea(display,backbuffer,window,gc,
185 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS,
186 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
187 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS);
188 if (redraw_mask & REDRAW_VIDEO_2)
189 XCopyArea(display,backbuffer,window,gc,
190 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS,
191 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
192 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS);
193 if (redraw_mask & REDRAW_VIDEO_3)
194 XCopyArea(display,backbuffer,window,gc,
195 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS,
196 VIDEO_CONTROL_XSIZE,VIDEO_CONTROL_YSIZE,
197 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS);
200 if (redraw_mask & REDRAW_DOOR_3)
201 XCopyArea(display, backbuffer, window, gc,
202 EX, EY, EXSIZE, EYSIZE,
204 redraw_mask &= ~REDRAW_DOORS;
207 if (redraw_mask & REDRAW_MICROLEVEL)
209 XCopyArea(display,backbuffer,window,gc,
210 MICROLEV_XPOS, MICROLEV_YPOS, MICROLEV_XSIZE, MICROLEV_YSIZE,
211 MICROLEV_XPOS, MICROLEV_YPOS);
212 XCopyArea(display,backbuffer,window,gc,
213 SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE,
214 SX, MICROLABEL_YPOS);
215 redraw_mask &= ~REDRAW_MICROLEVEL;
218 if (redraw_mask & REDRAW_TILES)
220 for(x=0; x<SCR_FIELDX; x++)
221 for(y=0; y<SCR_FIELDY; y++)
222 if (redraw[redraw_x1 + x][redraw_y1 + y])
223 XCopyArea(display, buffer, window, gc,
224 FX + x * TILEX, FX + y * TILEY, TILEX, TILEY,
225 SX + x * TILEX, SY + y * TILEY);
230 for(x=0; x<MAX_BUF_XSIZE; x++)
231 for(y=0; y<MAX_BUF_YSIZE; y++)
240 long fading_delay = 300;
242 if (setup.fading && (redraw_mask & REDRAW_FIELD))
249 XFillRectangle(display,window,gc,
250 REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
253 for(i=0;i<2*FULL_SYSIZE;i++)
255 for(y=0;y<FULL_SYSIZE;y++)
257 XCopyArea(display,backbuffer,window,gc,
258 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
266 for(i=1;i<FULL_SYSIZE;i+=2)
267 XCopyArea(display,backbuffer,window,gc,
268 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
274 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,0);
275 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
276 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
280 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,-1);
281 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
282 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
286 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,-1);
287 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
288 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
292 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,0);
293 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
294 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
298 redraw_mask &= ~REDRAW_MAIN;
307 XFillRectangle(display, backbuffer, gc,
308 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
310 if (setup.soft_scrolling && game_status == PLAYING)
312 XFillRectangle(display, fieldbuffer, gc, 0, 0, FXSIZE, FYSIZE);
313 SetDrawtoField(DRAW_BUFFERED);
316 SetDrawtoField(DRAW_BACKBUFFER);
318 if (setup.direct_draw && game_status == PLAYING)
320 XFillRectangle(display, window, gc,
321 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
322 SetDrawtoField(DRAW_DIRECT);
325 redraw_mask |= REDRAW_FIELD;
328 void DrawTextFCentered(int y, int font_type, char *format, ...)
330 char buffer[FULL_SXSIZE / FONT3_XSIZE + 10];
334 font_xsize = (font_type < FC_SPECIAL1 ? FONT2_XSIZE :
335 font_type < FC_SPECIAL2 ? FONT3_XSIZE : FONT4_XSIZE);
337 va_start(ap, format);
338 vsprintf(buffer, format, ap);
341 DrawText(SX + (SXSIZE - strlen(buffer) * font_xsize) / 2, SY + y,
342 buffer, FS_SMALL, font_type);
345 void DrawTextF(int x, int y, int font_type, char *format, ...)
347 char buffer[FULL_SXSIZE / FONT3_XSIZE + 10];
350 va_start(ap, format);
351 vsprintf(buffer, format, ap);
354 DrawText(SX + x, SY + y, buffer, FS_SMALL, font_type);
357 void DrawText(int x, int y, char *text, int font_size, int font_type)
359 DrawTextExt(drawto, gc, x, y, text, font_size, font_type);
362 redraw_mask |= REDRAW_FIELD;
364 redraw_mask |= REDRAW_DOOR_1;
367 void DrawTextExt(Drawable d, GC gc, int x, int y,
368 char *text, int font_size, int font_type)
370 int font_width, font_height, font_start;
372 boolean print_inverse = FALSE;
374 if (font_size != FS_SMALL && font_size != FS_BIG)
375 font_size = FS_SMALL;
376 if (font_type < FC_RED || font_type > FC_SPECIAL2)
379 font_width = (font_size == FS_BIG ? FONT1_XSIZE :
380 font_type < FC_SPECIAL1 ? FONT2_XSIZE :
381 font_type < FC_SPECIAL2 ? FONT3_XSIZE : FONT4_XSIZE);
382 font_height = (font_size == FS_BIG ? FONT1_XSIZE :
383 font_type < FC_SPECIAL2 ? FONT2_XSIZE : FONT4_XSIZE);
384 font_pixmap = (font_size == FS_BIG ? PIX_BIGFONT : PIX_SMALLFONT);
385 font_start = (font_type * (font_size == FS_BIG ? FONT1_YSIZE : FONT2_YSIZE) *
386 FONT_LINES_PER_FONT);
392 if (c == '~' && font_size == FS_SMALL && font_type <= FC_YELLOW)
394 print_inverse = TRUE;
398 if (c >= 'a' && c <= 'z')
400 else if (c == 'ä' || c == 'Ä')
402 else if (c == 'ö' || c == 'Ö')
404 else if (c == 'ü' || c == 'Ü')
407 if (c >= 32 && c <= 95)
409 int src_x = ((c - 32) % FONT_CHARS_PER_LINE) * font_width;
410 int src_y = ((c - 32) / FONT_CHARS_PER_LINE) * font_height + font_start;
411 int dest_x = x, dest_y = y;
415 XCopyArea(display, pix[font_pixmap], d, gc,
416 FONT_CHARS_PER_LINE * font_width,
417 3 * font_height + font_start,
418 font_width, font_height, x, y);
420 XSetClipOrigin(display, clip_gc[font_pixmap],
421 dest_x - src_x, dest_y - src_y);
422 XCopyArea(display, pix[font_pixmap], d, clip_gc[font_pixmap],
423 0, 0, font_width, font_height, dest_x, dest_y);
426 XCopyArea(display, pix[font_pixmap], d, gc,
427 src_x, src_y, font_width, font_height, dest_x, dest_y);
434 void DrawAllPlayers()
438 for(i=0; i<MAX_PLAYERS; i++)
439 if (stored_player[i].active)
440 DrawPlayer(&stored_player[i]);
443 void DrawPlayerField(int x, int y)
448 DrawPlayer(PLAYERINFO(x,y));
451 void DrawPlayer(struct PlayerInfo *player)
453 int jx = player->jx, jy = player->jy;
454 int last_jx = player->last_jx, last_jy = player->last_jy;
455 int next_jx = jx + (jx - last_jx), next_jy = jy + (jy - last_jy);
456 int sx = SCREENX(jx), sy = SCREENY(jy);
457 int sxx = 0, syy = 0;
458 int element = Feld[jx][jy];
461 if (!player->active || player->gone ||
462 !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
466 if (!IN_LEV_FIELD(jx,jy))
468 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
469 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
470 printf("DrawPlayerField(): This should never happen!\n");
475 if (element == EL_EXPLODING)
478 /* draw things in the field the player is leaving, if needed */
480 if (last_jx != jx || last_jy != jy)
482 if (Store[last_jx][last_jy])
484 DrawLevelElement(last_jx, last_jy, Store[last_jx][last_jy]);
485 DrawLevelFieldThruMask(last_jx, last_jy);
487 else if (Feld[last_jx][last_jy] == EL_DYNAMIT)
488 DrawDynamite(last_jx, last_jy);
490 DrawLevelField(last_jx, last_jy);
492 if (player->Pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
496 if (Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
497 DrawLevelElement(next_jx, next_jy, EL_SOKOBAN_FELD_LEER);
499 DrawLevelElement(next_jx, next_jy, EL_LEERRAUM);
502 DrawLevelField(next_jx, next_jy);
506 if (!IN_SCR_FIELD(sx, sy))
509 if (setup.direct_draw)
510 SetDrawtoField(DRAW_BUFFERED);
512 /* draw things behind the player, if needed */
515 DrawLevelElement(jx, jy, Store[jx][jy]);
516 else if (element != EL_DYNAMIT && element != EL_DYNABOMB)
517 DrawLevelField(jx, jy);
519 /* draw player himself */
521 if (game_emulation == EMU_SUPAPLEX)
524 if (player->MovDir == MV_LEFT)
526 (player->Pushing ? GFX_MURPHY_PUSH_LEFT : GFX_MURPHY_LEFT);
527 else if (player->MovDir == MV_RIGHT)
529 (player->Pushing ? GFX_MURPHY_PUSH_RIGHT : GFX_MURPHY_RIGHT);
530 else if (player->MovDir == MV_UP)
531 graphic = GFX_MURPHY_UP;
532 else if (player->MovDir == MV_DOWN)
533 graphic = GFX_MURPHY_DOWN;
534 else /* MV_NO_MOVING */
535 graphic = GFX_SP_MURPHY;
540 graphic = GFX_SPIELER1_PUSH_LEFT;
542 graphic = GFX_SPIELER1_PUSH_RIGHT;
546 static int last_dir = MV_LEFT;
550 if (player->MovDir == MV_LEFT)
551 graphic = GFX_MURPHY_PUSH_LEFT;
552 else if (player->MovDir == MV_RIGHT)
553 graphic = GFX_MURPHY_PUSH_RIGHT;
554 else if (last_dir == MV_LEFT)
555 graphic = GFX_MURPHY_ANY_LEFT;
556 else if (last_dir == MV_RIGHT)
557 graphic = GFX_MURPHY_ANY_RIGHT;
559 graphic = GFX_SP_MURPHY;
561 else if (player->snapped)
563 if (player->MovDir == MV_LEFT)
564 graphic = GFX_MURPHY_SNAP_LEFT;
565 else if (player->MovDir == MV_RIGHT)
566 graphic = GFX_MURPHY_SNAP_RIGHT;
567 else if (player->MovDir == MV_UP)
568 graphic = GFX_MURPHY_SNAP_UP;
569 else if (player->MovDir == MV_DOWN)
570 graphic = GFX_MURPHY_SNAP_DOWN;
572 graphic = GFX_SP_MURPHY;
576 if (player->MovDir == MV_LEFT)
577 graphic = GFX_MURPHY_ANY_LEFT;
578 else if (player->MovDir == MV_RIGHT)
579 graphic = GFX_MURPHY_ANY_RIGHT;
580 else if (last_dir == MV_LEFT)
581 graphic = GFX_MURPHY_ANY_LEFT;
582 else if (last_dir == MV_RIGHT)
583 graphic = GFX_MURPHY_ANY_RIGHT;
585 graphic = GFX_SP_MURPHY;
588 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
589 last_dir = player->MovDir;
591 if (!player->Pushing && !player->snapped && player->MovDir != MV_NO_MOVING)
592 graphic -= player->Frame % 2;
596 if (player->MovDir == MV_LEFT)
598 (player->Pushing ? GFX_SPIELER1_PUSH_LEFT : GFX_SPIELER1_LEFT);
599 else if (player->MovDir == MV_RIGHT)
601 (player->Pushing ? GFX_SPIELER1_PUSH_RIGHT : GFX_SPIELER1_RIGHT);
602 else if (player->MovDir == MV_UP)
603 graphic = GFX_SPIELER1_UP;
604 else /* MV_DOWN || MV_NO_MOVING */
605 graphic = GFX_SPIELER1_DOWN;
607 graphic += player->index_nr * 3 * HEROES_PER_LINE;
608 graphic += player->Frame;
613 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
614 sxx = player->GfxPos;
616 syy = player->GfxPos;
619 if (!setup.soft_scrolling && ScreenMovPos)
622 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, NO_CUTTING);
624 if (player->Pushing && player->GfxPos)
626 int px = SCREENX(next_jx), py = SCREENY(next_jy);
628 if (Feld[jx][jy] == EL_SOKOBAN_FELD_LEER ||
629 Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
630 DrawGraphicShiftedThruMask(px, py, sxx, syy, GFX_SOKOBAN_OBJEKT,
634 int element = Feld[next_jx][next_jy];
635 int graphic = el2gfx(element);
637 if (element == EL_FELSBROCKEN && sxx)
639 int phase = (player->GfxPos / (TILEX/4));
641 if (player->MovDir == MV_LEFT)
644 graphic += (phase+4)%4;
647 DrawGraphicShifted(px, py, sxx, syy, graphic, NO_CUTTING, NO_MASKING);
651 /* draw things in front of player (EL_DYNAMIT || EL_DYNABOMB) */
653 if (element == EL_DYNAMIT || element == EL_DYNABOMB)
655 graphic = el2gfx(element);
657 if (element == EL_DYNAMIT)
659 if ((phase = (96 - MovDelay[jx][jy]) / 12) > 6)
664 if ((phase = ((96 - MovDelay[jx][jy]) / 6) % 8) > 3)
668 if (game_emulation == EMU_SUPAPLEX)
669 DrawGraphic(sx, sy, GFX_SP_DISK_RED);
671 DrawGraphicThruMask(sx, sy, graphic + phase);
674 if ((last_jx != jx || last_jy != jy) &&
675 Feld[last_jx][last_jy] == EL_EXPLODING)
677 int phase = Frame[last_jx][last_jy];
681 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy),
682 GFX_EXPLOSION + ((phase - 1) / delay - 1));
685 if (setup.direct_draw)
687 int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
688 int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
689 int x_size = TILEX * (1 + ABS(jx - last_jx));
690 int y_size = TILEY * (1 + ABS(jy - last_jy));
692 XCopyArea(display, drawto_field, window, gc,
693 dest_x, dest_y, x_size, y_size, dest_x, dest_y);
694 SetDrawtoField(DRAW_DIRECT);
697 MarkTileDirty(sx,sy);
700 static int getGraphicAnimationPhase(int frames, int delay, int mode)
704 if (mode == ANIM_OSCILLATE)
706 int max_anim_frames = 2 * frames - 2;
707 phase = (FrameCounter % (delay * max_anim_frames)) / delay;
708 phase = (phase < frames ? phase : max_anim_frames - phase);
711 phase = (FrameCounter % (delay * frames)) / delay;
713 if (mode == ANIM_REVERSE)
719 void DrawGraphicAnimationExt(int x, int y, int graphic,
720 int frames, int delay, int mode, int mask_mode)
722 int phase = getGraphicAnimationPhase(frames, delay, mode);
724 if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
726 if (mask_mode == USE_MASKING)
727 DrawGraphicThruMask(SCREENX(x), SCREENY(y), graphic + phase);
729 DrawGraphic(SCREENX(x), SCREENY(y), graphic + phase);
733 void DrawGraphicAnimation(int x, int y, int graphic,
734 int frames, int delay, int mode)
736 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, NO_MASKING);
739 void DrawGraphicAnimationThruMask(int x, int y, int graphic,
740 int frames, int delay, int mode)
742 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, USE_MASKING);
745 void getGraphicSource(int graphic, int *pixmap_nr, int *x, int *y)
747 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
749 graphic -= GFX_START_ROCKSSCREEN;
750 *pixmap_nr = PIX_BACK;
751 *x = SX + (graphic % GFX_PER_LINE) * TILEX;
752 *y = SY + (graphic / GFX_PER_LINE) * TILEY;
754 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
756 graphic -= GFX_START_ROCKSMORE;
757 *pixmap_nr = PIX_MORE;
758 *x = (graphic % MORE_PER_LINE) * TILEX;
759 *y = (graphic / MORE_PER_LINE) * TILEY;
761 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
763 graphic -= GFX_START_ROCKSHEROES;
764 *pixmap_nr = PIX_HEROES;
765 *x = (graphic % HEROES_PER_LINE) * TILEX;
766 *y = (graphic / HEROES_PER_LINE) * TILEY;
768 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
770 graphic -= GFX_START_ROCKSFONT;
771 *pixmap_nr = PIX_BIGFONT;
772 *x = (graphic % FONT_CHARS_PER_LINE) * TILEX;
773 *y = ((graphic / FONT_CHARS_PER_LINE) * TILEY +
774 FC_SPECIAL1 * FONT_LINES_PER_FONT * TILEY);
778 *pixmap_nr = PIX_MORE;
784 void DrawGraphic(int x, int y, int graphic)
787 if (!IN_SCR_FIELD(x,y))
789 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
790 printf("DrawGraphic(): This should never happen!\n");
795 DrawGraphicExt(drawto_field, gc, FX + x*TILEX, FY + y*TILEY, graphic);
799 void DrawGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
807 getGraphicSource(graphic, &pixmap_nr, &src_x, &src_y);
808 XCopyArea(display, pix[pixmap_nr], d, gc,
809 src_x, src_y, TILEX, TILEY, x, y);
813 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
815 graphic -= GFX_START_ROCKSSCREEN;
816 XCopyArea(display, pix[PIX_BACK], d, gc,
817 SX + (graphic % GFX_PER_LINE) * TILEX,
818 SY + (graphic / GFX_PER_LINE) * TILEY,
821 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
823 graphic -= GFX_START_ROCKSMORE;
824 XCopyArea(display, pix[PIX_MORE], d, gc,
825 (graphic % MORE_PER_LINE) * TILEX,
826 (graphic / MORE_PER_LINE) * TILEY,
829 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
831 graphic -= GFX_START_ROCKSHEROES;
832 XCopyArea(display, pix[PIX_HEROES], d, gc,
833 (graphic % HEROES_PER_LINE) * TILEX,
834 (graphic / HEROES_PER_LINE) * TILEY,
837 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
839 graphic -= GFX_START_ROCKSFONT;
840 XCopyArea(display, pix[PIX_BIGFONT], d, gc,
841 (graphic % FONT_CHARS_PER_LINE) * TILEX,
842 (graphic / FONT_CHARS_PER_LINE) * TILEY +
843 FC_SPECIAL1 * FONT_LINES_PER_FONT * TILEY,
847 XFillRectangle(display, d, gc, x, y, TILEX, TILEY);
853 void DrawGraphicThruMask(int x, int y, int graphic)
856 if (!IN_SCR_FIELD(x,y))
858 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
859 printf("DrawGraphicThruMask(): This should never happen!\n");
864 DrawGraphicThruMaskExt(drawto_field, FX + x*TILEX, FY + y*TILEY, graphic);
868 void DrawGraphicThruMaskExt(Drawable d, int dest_x, int dest_y, int graphic)
879 getGraphicSource(graphic, &pixmap_nr, &src_x, &src_y);
880 src_pixmap = pix[pixmap_nr];
881 drawing_gc = clip_gc[pixmap_nr];
890 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
892 src_pixmap = pix[PIX_BACK];
893 drawing_gc = clip_gc[PIX_BACK];
894 graphic -= GFX_START_ROCKSSCREEN;
895 src_x = SX + (graphic % GFX_PER_LINE) * TILEX;
896 src_y = SY + (graphic / GFX_PER_LINE) * TILEY;
898 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
900 src_pixmap = pix[PIX_MORE];
901 drawing_gc = clip_gc[PIX_MORE];
902 graphic -= GFX_START_ROCKSMORE;
903 src_x = (graphic % MORE_PER_LINE) * TILEX;
904 src_y = (graphic / MORE_PER_LINE) * TILEY;
906 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
908 src_pixmap = pix[PIX_HEROES];
909 drawing_gc = clip_gc[PIX_HEROES];
910 graphic -= GFX_START_ROCKSHEROES;
911 src_x = (graphic % HEROES_PER_LINE) * TILEX;
912 src_y = (graphic / HEROES_PER_LINE) * TILEY;
916 DrawGraphicExt(d, gc, dest_x,dest_y, graphic);
923 if (tile_clipmask[tile] != None)
925 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
926 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
927 XCopyArea(display, src_pixmap, d, tile_clip_gc,
928 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
933 printf("DrawGraphicThruMask(): tile '%d' needs clipping!\n", tile);
936 XSetClipOrigin(display, drawing_gc, dest_x-src_x, dest_y-src_y);
937 XCopyArea(display, src_pixmap, d, drawing_gc,
938 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
942 void DrawMiniGraphic(int x, int y, int graphic)
944 DrawMiniGraphicExt(drawto,gc, SX + x*MINI_TILEX, SY + y*MINI_TILEY, graphic);
945 MarkTileDirty(x/2, y/2);
948 void getMiniGraphicSource(int graphic, Pixmap *pixmap, int *x, int *y)
950 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
952 graphic -= GFX_START_ROCKSSCREEN;
953 *pixmap = pix[PIX_BACK];
954 *x = MINI_GFX_STARTX + (graphic % MINI_GFX_PER_LINE) * MINI_TILEX;
955 *y = MINI_GFX_STARTY + (graphic / MINI_GFX_PER_LINE) * MINI_TILEY;
957 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
959 graphic -= GFX_START_ROCKSMORE;
960 *pixmap = pix[PIX_MORE];
961 *x = MINI_MORE_STARTX + (graphic % MINI_MORE_PER_LINE) * MINI_TILEX;
962 *y = MINI_MORE_STARTY + (graphic / MINI_MORE_PER_LINE) * MINI_TILEY;
964 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
966 graphic -= GFX_START_ROCKSFONT;
967 *pixmap = pix[PIX_SMALLFONT];
968 *x = (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE;
969 *y = ((graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE +
970 FC_SPECIAL2 * FONT2_YSIZE * FONT_LINES_PER_FONT);
974 *pixmap = pix[PIX_MORE];
975 *x = MINI_MORE_STARTX;
976 *y = MINI_MORE_STARTY;
980 void DrawMiniGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
988 getMiniGraphicSource(graphic, &pixmap, &src_x, &src_y);
989 XCopyArea(display, pixmap, d, gc,
990 src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
994 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
996 graphic -= GFX_START_ROCKSSCREEN;
997 XCopyArea(display, pix[PIX_BACK], d, gc,
998 MINI_GFX_STARTX + (graphic % MINI_GFX_PER_LINE) * MINI_TILEX,
999 MINI_GFX_STARTY + (graphic / MINI_GFX_PER_LINE) * MINI_TILEY,
1000 MINI_TILEX, MINI_TILEY, x, y);
1002 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
1004 graphic -= GFX_START_ROCKSMORE;
1005 XCopyArea(display, pix[PIX_MORE], d, gc,
1006 MINI_MORE_STARTX + (graphic % MINI_MORE_PER_LINE) * MINI_TILEX,
1007 MINI_MORE_STARTY + (graphic / MINI_MORE_PER_LINE) * MINI_TILEY,
1008 MINI_TILEX, MINI_TILEY, x, y);
1010 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
1012 graphic -= GFX_START_ROCKSFONT;
1013 XCopyArea(display, pix[PIX_SMALLFONT], d, gc,
1014 (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE,
1015 (graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE +
1016 FC_SPECIAL2 * FONT2_YSIZE * FONT_LINES_PER_FONT,
1017 MINI_TILEX, MINI_TILEY, x, y);
1020 XFillRectangle(display, d, gc, x, y, MINI_TILEX, MINI_TILEY);
1026 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
1027 int cut_mode, int mask_mode)
1029 int width = TILEX, height = TILEY;
1031 int src_x, src_y, dest_x, dest_y;
1038 DrawGraphic(x, y, graphic);
1042 if (dx || dy) /* Verschiebung der Grafik? */
1044 if (x < BX1) /* Element kommt von links ins Bild */
1051 else if (x > BX2) /* Element kommt von rechts ins Bild */
1057 else if (x==BX1 && dx < 0) /* Element verläßt links das Bild */
1063 else if (x==BX2 && dx > 0) /* Element verläßt rechts das Bild */
1065 else if (dx) /* allg. Bewegung in x-Richtung */
1066 MarkTileDirty(x + SIGN(dx), y);
1068 if (y < BY1) /* Element kommt von oben ins Bild */
1070 if (cut_mode==CUT_BELOW) /* Element oberhalb des Bildes */
1078 else if (y > BY2) /* Element kommt von unten ins Bild */
1084 else if (y==BY1 && dy < 0) /* Element verläßt oben das Bild */
1090 else if (dy > 0 && cut_mode == CUT_ABOVE)
1092 if (y == BY2) /* Element unterhalb des Bildes */
1098 MarkTileDirty(x, y + 1);
1099 } /* Element verläßt unten das Bild */
1100 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1102 else if (dy) /* allg. Bewegung in y-Richtung */
1103 MarkTileDirty(x, y + SIGN(dy));
1106 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
1108 src_pixmap = pix[PIX_BACK];
1109 drawing_gc = clip_gc[PIX_BACK];
1110 graphic -= GFX_START_ROCKSSCREEN;
1111 src_x = SX + (graphic % GFX_PER_LINE) * TILEX + cx;
1112 src_y = SY + (graphic / GFX_PER_LINE) * TILEY + cy;
1114 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
1116 src_pixmap = pix[PIX_MORE];
1117 drawing_gc = clip_gc[PIX_MORE];
1118 graphic -= GFX_START_ROCKSMORE;
1119 src_x = (graphic % MORE_PER_LINE) * TILEX + cx;
1120 src_y = (graphic / MORE_PER_LINE) * TILEY + cy;
1122 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
1124 src_pixmap = pix[PIX_HEROES];
1125 drawing_gc = clip_gc[PIX_HEROES];
1126 graphic -= GFX_START_ROCKSHEROES;
1127 src_x = (graphic % HEROES_PER_LINE) * TILEX + cx;
1128 src_y = (graphic / HEROES_PER_LINE) * TILEY + cy;
1130 else /* big font graphics currently not allowed (and not needed) */
1133 dest_x = FX + x * TILEX + dx;
1134 dest_y = FY + y * TILEY + dy;
1137 if (!IN_SCR_FIELD(x,y))
1139 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1140 printf("DrawGraphicShifted(): This should never happen!\n");
1145 if (mask_mode == USE_MASKING)
1147 if (tile_clipmask[tile] != None)
1149 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
1150 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
1151 XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
1152 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
1157 printf("DrawGraphicShifted(): tile '%d' needs clipping!\n", tile);
1160 XSetClipOrigin(display, drawing_gc, dest_x - src_x, dest_y - src_y);
1161 XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
1162 src_x, src_y, width, height, dest_x, dest_y);
1166 XCopyArea(display, src_pixmap, drawto_field, gc,
1167 src_x, src_y, width, height, dest_x, dest_y);
1172 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
1175 DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, USE_MASKING);
1178 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1179 int cut_mode, int mask_mode)
1181 int ux = LEVELX(x), uy = LEVELY(y);
1182 int graphic = el2gfx(element);
1183 int phase8 = ABS(MovPos[ux][uy]) / (TILEX / 8);
1184 int phase4 = phase8 / 2;
1185 int phase2 = phase8 / 4;
1186 int dir = MovDir[ux][uy];
1188 if (element == EL_PACMAN || element == EL_KAEFER || element == EL_FLIEGER)
1190 graphic += 4 * !phase2;
1194 else if (dir == MV_LEFT)
1196 else if (dir == MV_DOWN)
1199 else if (element == EL_SP_SNIKSNAK)
1202 graphic = GFX_SP_SNIKSNAK_LEFT;
1203 else if (dir == MV_RIGHT)
1204 graphic = GFX_SP_SNIKSNAK_RIGHT;
1205 else if (dir == MV_UP)
1206 graphic = GFX_SP_SNIKSNAK_UP;
1208 graphic = GFX_SP_SNIKSNAK_DOWN;
1210 graphic += (phase8 < 4 ? phase8 : 7 - phase8);
1212 else if (element == EL_SP_ELECTRON)
1214 graphic = GFX2_SP_ELECTRON + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1216 else if (element == EL_MAULWURF || element == EL_PINGUIN ||
1217 element == EL_SCHWEIN || element == EL_DRACHE)
1220 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_LEFT :
1221 element == EL_PINGUIN ? GFX_PINGUIN_LEFT :
1222 element == EL_SCHWEIN ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
1223 else if (dir == MV_RIGHT)
1224 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_RIGHT :
1225 element == EL_PINGUIN ? GFX_PINGUIN_RIGHT :
1226 element == EL_SCHWEIN ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
1227 else if (dir == MV_UP)
1228 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_UP :
1229 element == EL_PINGUIN ? GFX_PINGUIN_UP :
1230 element == EL_SCHWEIN ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
1232 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_DOWN :
1233 element == EL_PINGUIN ? GFX_PINGUIN_DOWN :
1234 element == EL_SCHWEIN ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
1238 else if (element == EL_SONDE)
1240 graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1242 else if (element == EL_SALZSAEURE)
1244 graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_NORMAL);
1246 else if (element == EL_BUTTERFLY || element == EL_FIREFLY)
1250 else if ((element == EL_FELSBROCKEN || IS_GEM(element)) && !cut_mode)
1252 if (element != EL_SP_INFOTRON)
1253 graphic += phase2 * (element == EL_FELSBROCKEN ? 2 : 1);
1255 else if (element == EL_SIEB_LEER || element == EL_SIEB2_LEER ||
1256 element == EL_SIEB_VOLL || element == EL_SIEB2_VOLL)
1258 graphic += 3 + getGraphicAnimationPhase(4, 4, ANIM_REVERSE);
1260 else if (IS_AMOEBOID(element))
1262 graphic = (element == EL_AMOEBE_TOT ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
1263 graphic += (x + 2 * y + 4) % 4;
1265 else if (element == EL_MAUER_LEBT)
1267 boolean links_massiv = FALSE, rechts_massiv = FALSE;
1269 if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
1270 links_massiv = TRUE;
1271 if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
1272 rechts_massiv = TRUE;
1274 if (links_massiv && rechts_massiv)
1275 graphic = GFX_MAUERWERK;
1276 else if (links_massiv)
1277 graphic = GFX_MAUER_R;
1278 else if (rechts_massiv)
1279 graphic = GFX_MAUER_L;
1283 DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
1284 else if (mask_mode == USE_MASKING)
1285 DrawGraphicThruMask(x, y, graphic);
1287 DrawGraphic(x, y, graphic);
1290 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1291 int cut_mode, int mask_mode)
1293 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1294 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1295 cut_mode, mask_mode);
1298 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1301 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1304 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1307 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1310 void DrawScreenElementThruMask(int x, int y, int element)
1312 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1315 void DrawLevelElementThruMask(int x, int y, int element)
1317 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1320 void DrawLevelFieldThruMask(int x, int y)
1322 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1325 void ErdreichAnbroeckeln(int x, int y)
1327 int i, width, height, cx,cy;
1328 int ux = LEVELX(x), uy = LEVELY(y);
1329 int element, graphic;
1331 static int xy[4][2] =
1339 if (!IN_LEV_FIELD(ux, uy))
1342 element = Feld[ux][uy];
1344 if (element == EL_ERDREICH)
1346 if (!IN_SCR_FIELD(x, y))
1349 graphic = GFX_ERDENRAND;
1355 uxx = ux + xy[i][0];
1356 uyy = uy + xy[i][1];
1357 if (!IN_LEV_FIELD(uxx, uyy))
1360 element = Feld[uxx][uyy];
1362 if (element == EL_ERDREICH)
1365 if (i == 1 || i == 2)
1369 cx = (i == 2 ? TILEX - snip : 0);
1377 cy = (i == 3 ? TILEY - snip : 0);
1380 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1381 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1382 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1383 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1386 MarkTileDirty(x, y);
1390 graphic = GFX_ERDENRAND;
1394 int xx, yy, uxx, uyy;
1398 uxx = ux + xy[i][0];
1399 uyy = uy + xy[i][1];
1401 if (!IN_LEV_FIELD(uxx, uyy) || Feld[uxx][uyy] != EL_ERDREICH ||
1402 !IN_SCR_FIELD(xx, yy))
1405 if (i == 1 || i == 2)
1409 cx = (i == 1 ? TILEX - snip : 0);
1417 cy = (i==0 ? TILEY-snip : 0);
1420 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1421 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1422 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1423 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1425 MarkTileDirty(xx, yy);
1430 void DrawScreenElement(int x, int y, int element)
1432 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1433 ErdreichAnbroeckeln(x, y);
1436 void DrawLevelElement(int x, int y, int element)
1438 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1439 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1442 void DrawScreenField(int x, int y)
1444 int ux = LEVELX(x), uy = LEVELY(y);
1447 if (!IN_LEV_FIELD(ux, uy))
1449 if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
1450 element = EL_LEERRAUM;
1452 element = BorderElement;
1454 DrawScreenElement(x, y, element);
1458 element = Feld[ux][uy];
1460 if (IS_MOVING(ux, uy))
1462 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1463 boolean cut_mode = NO_CUTTING;
1465 if (Store[ux][uy] == EL_MORAST_LEER ||
1466 Store[ux][uy] == EL_SIEB_LEER ||
1467 Store[ux][uy] == EL_SIEB2_LEER ||
1468 Store[ux][uy] == EL_AMOEBE_NASS)
1469 cut_mode = CUT_ABOVE;
1470 else if (Store[ux][uy] == EL_MORAST_VOLL ||
1471 Store[ux][uy] == EL_SIEB_VOLL ||
1472 Store[ux][uy] == EL_SIEB2_VOLL)
1473 cut_mode = CUT_BELOW;
1475 if (cut_mode == CUT_ABOVE)
1476 DrawScreenElementShifted(x, y, 0, 0, Store[ux][uy], NO_CUTTING);
1478 DrawScreenElement(x, y, EL_LEERRAUM);
1481 DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1483 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1485 if (Store[ux][uy] == EL_SALZSAEURE)
1486 DrawLevelElementThruMask(ux, uy + 1, EL_SALZSAEURE);
1488 else if (IS_BLOCKED(ux, uy))
1493 boolean cut_mode = NO_CUTTING;
1495 Blocked2Moving(ux, uy, &oldx, &oldy);
1498 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1499 MovDir[oldx][oldy] == MV_RIGHT);
1501 if (Store[oldx][oldy] == EL_MORAST_LEER ||
1502 Store[oldx][oldy] == EL_SIEB_LEER ||
1503 Store[oldx][oldy] == EL_SIEB2_LEER ||
1504 Store[oldx][oldy] == EL_AMOEBE_NASS)
1505 cut_mode = CUT_ABOVE;
1507 DrawScreenElement(x, y, EL_LEERRAUM);
1508 element = Feld[oldx][oldy];
1511 DrawScreenElementShifted(sx,sy, MovPos[oldx][oldy],0,element,NO_CUTTING);
1513 DrawScreenElementShifted(sx,sy, 0,MovPos[oldx][oldy],element,cut_mode);
1515 else if (IS_DRAWABLE(element))
1516 DrawScreenElement(x, y, element);
1518 DrawScreenElement(x, y, EL_LEERRAUM);
1521 void DrawLevelField(int x, int y)
1523 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1524 DrawScreenField(SCREENX(x), SCREENY(y));
1525 else if (IS_MOVING(x, y))
1529 Moving2Blocked(x, y, &newx, &newy);
1530 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1531 DrawScreenField(SCREENX(newx), SCREENY(newy));
1533 else if (IS_BLOCKED(x, y))
1537 Blocked2Moving(x, y, &oldx, &oldy);
1538 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1539 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1543 void DrawMiniElement(int x, int y, int element)
1549 DrawMiniGraphic(x, y, -1);
1553 graphic = el2gfx(element);
1554 DrawMiniGraphic(x, y, graphic);
1557 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1559 int x = sx + scroll_x, y = sy + scroll_y;
1561 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1562 DrawMiniElement(sx, sy, EL_LEERRAUM);
1563 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1564 DrawMiniElement(sx, sy, Feld[x][y]);
1567 int steel_type, steel_position;
1570 { GFX_VSTEEL_UPPER_LEFT, GFX_ISTEEL_UPPER_LEFT },
1571 { GFX_VSTEEL_UPPER_RIGHT, GFX_ISTEEL_UPPER_RIGHT },
1572 { GFX_VSTEEL_LOWER_LEFT, GFX_ISTEEL_LOWER_LEFT },
1573 { GFX_VSTEEL_LOWER_RIGHT, GFX_ISTEEL_LOWER_RIGHT },
1574 { GFX_VSTEEL_VERTICAL, GFX_ISTEEL_VERTICAL },
1575 { GFX_VSTEEL_HORIZONTAL, GFX_ISTEEL_HORIZONTAL }
1578 steel_type = (BorderElement == EL_BETON ? 0 : 1);
1579 steel_position = (x == -1 && y == -1 ? 0 :
1580 x == lev_fieldx && y == -1 ? 1 :
1581 x == -1 && y == lev_fieldy ? 2 :
1582 x == lev_fieldx && y == lev_fieldy ? 3 :
1583 x == -1 || x == lev_fieldx ? 4 :
1584 y == -1 || y == lev_fieldy ? 5 : -1);
1586 if (steel_position != -1)
1587 DrawMiniGraphic(sx, sy, border[steel_position][steel_type]);
1591 if (x == -1 && y == -1)
1592 DrawMiniGraphic(sx, sy, GFX_STEEL_UPPER_LEFT);
1593 else if (x == lev_fieldx && y == -1)
1594 DrawMiniGraphic(sx, sy, GFX_STEEL_UPPER_RIGHT);
1595 else if (x == -1 && y == lev_fieldy)
1596 DrawMiniGraphic(sx, sy, GFX_STEEL_LOWER_LEFT);
1597 else if (x == lev_fieldx && y == lev_fieldy)
1598 DrawMiniGraphic(sx, sy, GFX_STEEL_LOWER_RIGHT);
1599 else if (x == -1 || x == lev_fieldx)
1600 DrawMiniGraphic(sx, sy, GFX_STEEL_VERTICAL);
1601 else if (y == -1 || y == lev_fieldy)
1602 DrawMiniGraphic(sx, sy, GFX_STEEL_HORIZONTAL);
1609 void DrawMicroElement(int xpos, int ypos, int element)
1613 if (element == EL_LEERRAUM)
1616 graphic = el2gfx(element);
1618 if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
1620 graphic -= GFX_START_ROCKSMORE;
1621 XCopyArea(display, pix[PIX_MORE], drawto, gc,
1622 MICRO_MORE_STARTX + (graphic % MICRO_MORE_PER_LINE) *MICRO_TILEX,
1623 MICRO_MORE_STARTY + (graphic / MICRO_MORE_PER_LINE) *MICRO_TILEY,
1624 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1627 XCopyArea(display, pix[PIX_BACK], drawto, gc,
1628 MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX,
1629 MICRO_GFX_STARTY + (graphic / MICRO_GFX_PER_LINE) * MICRO_TILEY,
1630 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1639 for(x=BX1; x<=BX2; x++)
1640 for(y=BY1; y<=BY2; y++)
1641 DrawScreenField(x, y);
1643 if (setup.soft_scrolling)
1644 XCopyArea(display, fieldbuffer, backbuffer, gc,
1645 FX, FY, SXSIZE, SYSIZE, SX, SY);
1647 redraw_mask |= (REDRAW_FIELD | REDRAW_FROM_BACKBUFFER);
1650 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1654 for(x=0; x<size_x; x++)
1655 for(y=0; y<size_y; y++)
1656 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1658 redraw_mask |= REDRAW_FIELD;
1661 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1665 /* determine border element for this level */
1668 XFillRectangle(display, drawto, gc,
1669 xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
1671 if (lev_fieldx < STD_LEV_FIELDX)
1672 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1673 if (lev_fieldy < STD_LEV_FIELDY)
1674 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1676 xpos += MICRO_TILEX;
1677 ypos += MICRO_TILEY;
1679 for(x=-1; x<=STD_LEV_FIELDX; x++)
1681 for(y=-1; y<=STD_LEV_FIELDY; y++)
1683 int lx = from_x + x, ly = from_y + y;
1685 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1686 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1688 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1)
1689 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1694 redraw_mask |= REDRAW_MICROLEVEL;
1697 static void DrawMicroLevelLabelExt(int mode)
1699 char label_text[100];
1701 XFillRectangle(display, drawto,gc,
1702 SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
1704 strcpy(label_text, (mode == 1 ? level.name :
1705 mode == 2 ? "created by" :
1706 mode == 3 ? level.author : ""));
1708 if (strlen(label_text) > 0)
1710 int size, lxpos, lypos;
1712 label_text[SXSIZE / FONT4_XSIZE] = '\0';
1714 size = strlen(label_text);
1715 lxpos = SX + (SXSIZE - size * FONT4_XSIZE) / 2;
1716 lypos = MICROLABEL_YPOS;
1718 DrawText(lxpos, lypos, label_text, FS_SMALL, FC_SPECIAL2);
1721 redraw_mask |= REDRAW_MICROLEVEL;
1724 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1726 static unsigned long scroll_delay = 0;
1727 static unsigned long label_delay = 0;
1728 static int from_x, from_y, scroll_direction;
1729 static int label_state, label_counter;
1733 from_x = from_y = 0;
1734 scroll_direction = MV_RIGHT;
1738 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1739 DrawMicroLevelLabelExt(label_state);
1741 /* initialize delay counters */
1742 DelayReached(&scroll_delay, 0);
1743 DelayReached(&label_delay, 0);
1748 /* scroll micro level, if needed */
1749 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1750 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1752 switch (scroll_direction)
1758 scroll_direction = MV_UP;
1762 if (from_x < lev_fieldx - STD_LEV_FIELDX)
1765 scroll_direction = MV_DOWN;
1772 scroll_direction = MV_RIGHT;
1776 if (from_y < lev_fieldy - STD_LEV_FIELDY)
1779 scroll_direction = MV_LEFT;
1786 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1789 /* redraw micro level label, if needed */
1790 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1791 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1792 strcmp(level.author, leveldir[leveldir_nr].name) != 0 &&
1793 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1795 label_counter = (label_counter + 1) % 23;
1796 label_state = (label_counter >= 0 && label_counter <= 7 ? 1 :
1797 label_counter >= 9 && label_counter <= 12 ? 2 :
1798 label_counter >= 14 && label_counter <= 21 ? 3 : 0);
1799 DrawMicroLevelLabelExt(label_state);
1803 int REQ_in_range(int x, int y)
1805 if (y > DY+249 && y < DY+278)
1807 if (x > DX+1 && x < DX+48)
1809 else if (x > DX+51 && x < DX+98)
1815 boolean Request(char *text, unsigned int req_state)
1817 int mx, my, ty, result = -1;
1818 unsigned int old_door_state;
1821 /* pause network game while waiting for request to answer */
1822 if (options.network &&
1823 game_status == PLAYING &&
1824 req_state & REQUEST_WAIT_FOR)
1825 SendToServer_PausePlaying();
1828 old_door_state = GetDoorState();
1832 CloseDoor(DOOR_CLOSE_1);
1834 /* save old door content */
1835 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1836 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
1837 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
1839 /* clear door drawing field */
1841 XFillRectangle(display, pix[PIX_DB_DOOR], gc,
1842 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE);
1844 XFillRectangle(display, drawto, gc, DX, DY, DXSIZE, DYSIZE);
1847 /* write text for request */
1848 for(ty=0; ty<13; ty++)
1856 for(tl=0,tx=0; tx<7; tl++,tx++)
1859 if (!tc || tc == 32)
1871 DrawTextExt(pix[PIX_DB_DOOR], gc,
1872 DOOR_GFX_PAGEX1 + 51 - (tl * 14)/2, SY + ty * 16,
1873 txt, FS_SMALL, FC_YELLOW);
1875 DrawTextExt(drawto, gc,
1876 DX + 51 - (tl * 14)/2, DY + 8 + ty * 16,
1877 txt, FS_SMALL, FC_YELLOW);
1879 text += tl + (tc == 32 ? 1 : 0);
1883 if (req_state & REQ_ASK)
1885 DrawYesNoButton(BUTTON_OK, DB_INIT);
1886 DrawYesNoButton(BUTTON_NO, DB_INIT);
1888 else if (req_state & REQ_CONFIRM)
1890 DrawConfirmButton(BUTTON_CONFIRM, DB_INIT);
1892 else if (req_state & REQ_PLAYER)
1894 DrawPlayerButton(BUTTON_PLAYER_1, DB_INIT);
1895 DrawPlayerButton(BUTTON_PLAYER_2, DB_INIT);
1896 DrawPlayerButton(BUTTON_PLAYER_3, DB_INIT);
1897 DrawPlayerButton(BUTTON_PLAYER_4, DB_INIT);
1901 if (req_state & REQ_ASK)
1903 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
1904 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
1906 else if (req_state & REQ_CONFIRM)
1908 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
1910 else if (req_state & REQ_PLAYER)
1912 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
1913 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
1914 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
1915 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
1918 /* copy request gadgets to door backbuffer */
1919 XCopyArea(display, drawto, pix[PIX_DB_DOOR], gc,
1920 DX, DY, DXSIZE, DYSIZE,
1921 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1925 OpenDoor(DOOR_OPEN_1);
1928 if (!(req_state & REQUEST_WAIT_FOR))
1931 if (game_status != MAINMENU)
1934 button_status = MB_RELEASED;
1936 request_gadget_id = -1;
1940 if (XPending(display))
1944 XNextEvent(display, &event);
1957 if (event.type == MotionNotify)
1964 if (!XQueryPointer(display, window, &root, &child,
1965 &root_x, &root_y, &win_x, &win_y, &mask))
1971 motion_status = TRUE;
1972 mx = ((XMotionEvent *) &event)->x;
1973 my = ((XMotionEvent *) &event)->y;
1977 motion_status = FALSE;
1978 mx = ((XButtonEvent *) &event)->x;
1979 my = ((XButtonEvent *) &event)->y;
1980 if (event.type==ButtonPress)
1981 button_status = ((XButtonEvent *) &event)->button;
1983 button_status = MB_RELEASED;
1989 if (req_state & REQ_ASK)
1990 choice = CheckYesNoButtons(mx,my,button_status);
1991 else if (req_state & REQ_CONFIRM)
1992 choice = CheckConfirmButton(mx,my,button_status);
1994 choice = CheckPlayerButtons(mx,my,button_status);
2004 case BUTTON_CONFIRM:
2005 result = TRUE | FALSE;
2008 case BUTTON_PLAYER_1:
2011 case BUTTON_PLAYER_2:
2014 case BUTTON_PLAYER_3:
2017 case BUTTON_PLAYER_4:
2026 /* this sets 'request_gadget_id' */
2027 HandleGadgets(mx, my, button_status);
2029 switch(request_gadget_id)
2031 case TOOL_CTRL_ID_YES:
2034 case TOOL_CTRL_ID_NO:
2037 case TOOL_CTRL_ID_CONFIRM:
2038 result = TRUE | FALSE;
2041 case TOOL_CTRL_ID_PLAYER_1:
2044 case TOOL_CTRL_ID_PLAYER_2:
2047 case TOOL_CTRL_ID_PLAYER_3:
2050 case TOOL_CTRL_ID_PLAYER_4:
2063 switch(XLookupKeysym((XKeyEvent *)&event,
2064 ((XKeyEvent *)&event)->state))
2077 if (req_state & REQ_PLAYER)
2082 key_joystick_mapping = 0;
2086 HandleOtherEvents(&event);
2090 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2092 int joy = AnyJoystick();
2094 if (joy & JOY_BUTTON_1)
2096 else if (joy & JOY_BUTTON_2)
2102 /* don't eat all CPU time */
2106 if (game_status != MAINMENU)
2111 if (!(req_state & REQ_STAY_OPEN))
2113 CloseDoor(DOOR_CLOSE_1);
2115 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
2117 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
2118 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
2119 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
2120 OpenDoor(DOOR_OPEN_1);
2127 /* continue network game after request */
2128 if (options.network &&
2129 game_status == PLAYING &&
2130 req_state & REQUEST_WAIT_FOR)
2131 SendToServer_ContinuePlaying();
2137 unsigned int OpenDoor(unsigned int door_state)
2139 unsigned int new_door_state;
2141 if (door_state & DOOR_COPY_BACK)
2143 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
2144 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
2145 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2146 door_state &= ~DOOR_COPY_BACK;
2149 new_door_state = MoveDoor(door_state);
2151 return(new_door_state);
2154 unsigned int CloseDoor(unsigned int door_state)
2156 unsigned int new_door_state;
2158 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
2159 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2160 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
2161 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2163 new_door_state = MoveDoor(door_state);
2165 return(new_door_state);
2168 unsigned int GetDoorState()
2170 return(MoveDoor(DOOR_GET_STATE));
2173 unsigned int MoveDoor(unsigned int door_state)
2175 static int door1 = DOOR_OPEN_1;
2176 static int door2 = DOOR_CLOSE_2;
2177 static unsigned long door_delay = 0;
2178 int x, start, stepsize = 2;
2179 unsigned long door_delay_value = stepsize * 5;
2181 if (door_state == DOOR_GET_STATE)
2182 return(door1 | door2);
2184 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2185 door_state &= ~DOOR_OPEN_1;
2186 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2187 door_state &= ~DOOR_CLOSE_1;
2188 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2189 door_state &= ~DOOR_OPEN_2;
2190 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2191 door_state &= ~DOOR_CLOSE_2;
2193 if (setup.quick_doors)
2196 door_delay_value = 0;
2197 StopSound(SND_OEFFNEN);
2200 if (door_state & DOOR_ACTION)
2202 if (!(door_state & DOOR_NO_DELAY))
2203 PlaySoundStereo(SND_OEFFNEN, PSND_MAX_RIGHT);
2205 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2207 for(x=start; x<=DXSIZE; x+=stepsize)
2209 WaitUntilDelayReached(&door_delay, door_delay_value);
2211 if (door_state & DOOR_ACTION_1)
2213 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
2214 int j = (DXSIZE - i) / 3;
2216 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
2217 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
2218 DXSIZE,DYSIZE - i/2, DX, DY);
2220 XFillRectangle(display, drawto, gc, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
2222 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2223 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2224 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
2225 DXSIZE, DOOR_GFX_PAGEY1, i, 77, DX + DXSIZE - i, DY + j);
2226 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2227 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63, DX + DXSIZE - i,
2229 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2230 DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
2231 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2232 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j, DX, DY);
2233 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2234 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63, DX, DY + 140 - j);
2236 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2237 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2239 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2240 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2242 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2243 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2244 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2245 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2246 DX + DXSIZE - i, DY + 77 + j);
2247 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2248 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2249 DX + DXSIZE - i, DY + 203 + j);
2251 redraw_mask |= REDRAW_DOOR_1;
2254 if (door_state & DOOR_ACTION_2)
2256 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
2257 int j = (VXSIZE - i) / 3;
2259 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
2260 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
2261 VXSIZE, VYSIZE - i/2, VX, VY);
2263 XFillRectangle(display, drawto, gc, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
2265 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2266 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2267 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2268 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2, VX + VXSIZE-i, VY+j);
2269 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2270 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2271 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
2272 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j, VX, VY);
2274 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2275 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2,
2276 VX, VY + VYSIZE / 2 - j);
2277 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2278 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2279 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2280 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2 - j,
2281 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2283 redraw_mask |= REDRAW_DOOR_2;
2291 XCopyArea(display, drawto, window, gc, DX, DY, DXSIZE, DYSIZE, DX, DY);
2296 if (game_status == MAINMENU)
2301 if (setup.quick_doors)
2302 StopSound(SND_OEFFNEN);
2304 if (door_state & DOOR_ACTION_1)
2305 door1 = door_state & DOOR_ACTION_1;
2306 if (door_state & DOOR_ACTION_2)
2307 door2 = door_state & DOOR_ACTION_2;
2309 return(door1 | door2);
2312 int ReadPixel(Drawable d, int x, int y)
2314 XImage *pixel_image;
2315 unsigned long pixel_value;
2317 pixel_image = XGetImage(display, d, x, y, 1, 1, AllPlanes, ZPixmap);
2318 pixel_value = XGetPixel(pixel_image, 0, 0);
2320 XDestroyImage(pixel_image);
2325 /* ---------- new tool button stuff ---------------------------------------- */
2327 /* graphic position values for tool buttons */
2328 #define TOOL_BUTTON_YES_XPOS 2
2329 #define TOOL_BUTTON_YES_YPOS 250
2330 #define TOOL_BUTTON_YES_GFX_YPOS 0
2331 #define TOOL_BUTTON_YES_XSIZE 46
2332 #define TOOL_BUTTON_YES_YSIZE 28
2333 #define TOOL_BUTTON_NO_XPOS 52
2334 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2335 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2336 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2337 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2338 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2339 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2340 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2341 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2342 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2343 #define TOOL_BUTTON_PLAYER_XSIZE 30
2344 #define TOOL_BUTTON_PLAYER_YSIZE 30
2345 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2346 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2347 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2348 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2349 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2350 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2351 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2352 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2353 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2354 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2355 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2356 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2357 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2358 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2359 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2360 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2361 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2362 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2363 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2364 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2373 } toolbutton_info[NUM_TOOL_BUTTONS] =
2376 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2377 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2378 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2383 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2384 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2385 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2390 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2391 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2392 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2393 TOOL_CTRL_ID_CONFIRM,
2397 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2398 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2399 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2400 TOOL_CTRL_ID_PLAYER_1,
2404 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2405 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2406 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2407 TOOL_CTRL_ID_PLAYER_2,
2411 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2412 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2413 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2414 TOOL_CTRL_ID_PLAYER_3,
2418 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2419 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2420 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2421 TOOL_CTRL_ID_PLAYER_4,
2426 void CreateToolButtons()
2430 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2432 Pixmap gd_pixmap = pix[PIX_DOOR];
2433 Pixmap deco_pixmap = None;
2434 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2435 struct GadgetInfo *gi;
2436 unsigned long event_mask;
2437 int gd_xoffset, gd_yoffset;
2438 int gd_x1, gd_x2, gd_y;
2441 event_mask = GD_EVENT_RELEASED;
2443 gd_xoffset = toolbutton_info[i].xpos;
2444 gd_yoffset = toolbutton_info[i].ypos;
2445 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2446 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2447 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2449 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2451 getMiniGraphicSource(GFX_SPIELER1 + id - TOOL_CTRL_ID_PLAYER_1,
2452 &deco_pixmap, &deco_x, &deco_y);
2453 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2454 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2457 gi = CreateGadget(GDI_CUSTOM_ID, id,
2458 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2459 GDI_X, DX + toolbutton_info[i].x,
2460 GDI_Y, DY + toolbutton_info[i].y,
2461 GDI_WIDTH, toolbutton_info[i].width,
2462 GDI_HEIGHT, toolbutton_info[i].height,
2463 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2464 GDI_STATE, GD_BUTTON_UNPRESSED,
2465 GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y,
2466 GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y,
2467 GDI_DECORATION_DESIGN, deco_pixmap, deco_x, deco_y,
2468 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2469 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2470 GDI_DECORATION_SHIFTING, 1, 1,
2471 GDI_EVENT_MASK, event_mask,
2472 GDI_CALLBACK_ACTION, HandleToolButtons,
2476 Error(ERR_EXIT, "cannot create gadget");
2478 tool_gadget[id] = gi;
2482 static void UnmapToolButtons()
2486 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2487 UnmapGadget(tool_gadget[i]);
2490 static void HandleToolButtons(struct GadgetInfo *gi)
2492 request_gadget_id = gi->custom_id;
2496 int id = gi->custom_id;
2498 if (game_status != PLAYING)
2503 case GAME_CTRL_ID_STOP:
2506 CloseDoor(DOOR_CLOSE_1);
2507 game_status = MAINMENU;
2512 if (Request("Do you really want to quit the game ?",
2513 REQ_ASK | REQ_STAY_CLOSED))
2516 if (options.network)
2517 SendToServer_StopPlaying();
2521 game_status = MAINMENU;
2526 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
2529 case GAME_CTRL_ID_PAUSE:
2530 if (options.network)
2534 SendToServer_ContinuePlaying();
2536 SendToServer_PausePlaying();
2543 case GAME_CTRL_ID_PLAY:
2547 if (options.network)
2548 SendToServer_ContinuePlaying();
2552 tape.pausing = FALSE;
2553 DrawVideoDisplay(VIDEO_STATE_PAUSE_OFF,0);
2558 case SOUND_CTRL_ID_MUSIC:
2559 if (setup.sound_music)
2561 setup.sound_music = FALSE;
2562 FadeSound(background_loop[level_nr % num_bg_loops]);
2564 else if (sound_loops_allowed)
2566 setup.sound = setup.sound_music = TRUE;
2567 PlaySoundLoop(background_loop[level_nr % num_bg_loops]);
2571 case SOUND_CTRL_ID_LOOPS:
2572 if (setup.sound_loops)
2573 setup.sound_loops = FALSE;
2574 else if (sound_loops_allowed)
2575 setup.sound = setup.sound_loops = TRUE;
2578 case SOUND_CTRL_ID_SIMPLE:
2579 if (setup.sound_simple)
2580 setup.sound_simple = FALSE;
2581 else if (sound_status==SOUND_AVAILABLE)
2582 setup.sound = setup.sound_simple = TRUE;
2594 int el2gfx(int element)
2598 case EL_LEERRAUM: return -1;
2599 case EL_ERDREICH: return GFX_ERDREICH;
2600 case EL_MAUERWERK: return GFX_MAUERWERK;
2601 case EL_FELSBODEN: return GFX_FELSBODEN;
2602 case EL_FELSBROCKEN: return GFX_FELSBROCKEN;
2603 case EL_SCHLUESSEL: return GFX_SCHLUESSEL;
2604 case EL_EDELSTEIN: return GFX_EDELSTEIN;
2605 case EL_AUSGANG_ZU: return GFX_AUSGANG_ZU;
2606 case EL_AUSGANG_ACT: return GFX_AUSGANG_ACT;
2607 case EL_AUSGANG_AUF: return GFX_AUSGANG_AUF;
2608 case EL_SPIELFIGUR: return GFX_SPIELFIGUR;
2609 case EL_SPIELER1: return GFX_SPIELER1;
2610 case EL_SPIELER2: return GFX_SPIELER2;
2611 case EL_SPIELER3: return GFX_SPIELER3;
2612 case EL_SPIELER4: return GFX_SPIELER4;
2613 case EL_KAEFER: return GFX_KAEFER;
2614 case EL_KAEFER_R: return GFX_KAEFER_R;
2615 case EL_KAEFER_O: return GFX_KAEFER_O;
2616 case EL_KAEFER_L: return GFX_KAEFER_L;
2617 case EL_KAEFER_U: return GFX_KAEFER_U;
2618 case EL_FLIEGER: return GFX_FLIEGER;
2619 case EL_FLIEGER_R: return GFX_FLIEGER_R;
2620 case EL_FLIEGER_O: return GFX_FLIEGER_O;
2621 case EL_FLIEGER_L: return GFX_FLIEGER_L;
2622 case EL_FLIEGER_U: return GFX_FLIEGER_U;
2623 case EL_BUTTERFLY: return GFX_BUTTERFLY;
2624 case EL_BUTTERFLY_R: return GFX_BUTTERFLY_R;
2625 case EL_BUTTERFLY_O: return GFX_BUTTERFLY_O;
2626 case EL_BUTTERFLY_L: return GFX_BUTTERFLY_L;
2627 case EL_BUTTERFLY_U: return GFX_BUTTERFLY_U;
2628 case EL_FIREFLY: return GFX_FIREFLY;
2629 case EL_FIREFLY_R: return GFX_FIREFLY_R;
2630 case EL_FIREFLY_O: return GFX_FIREFLY_O;
2631 case EL_FIREFLY_L: return GFX_FIREFLY_L;
2632 case EL_FIREFLY_U: return GFX_FIREFLY_U;
2633 case EL_MAMPFER: return GFX_MAMPFER;
2634 case EL_ROBOT: return GFX_ROBOT;
2635 case EL_BETON: return GFX_BETON;
2636 case EL_DIAMANT: return GFX_DIAMANT;
2637 case EL_MORAST_LEER: return GFX_MORAST_LEER;
2638 case EL_MORAST_VOLL: return GFX_MORAST_VOLL;
2639 case EL_TROPFEN: return GFX_TROPFEN;
2640 case EL_BOMBE: return GFX_BOMBE;
2641 case EL_SIEB_INAKTIV: return GFX_SIEB_INAKTIV;
2642 case EL_SIEB_LEER: return GFX_SIEB_LEER;
2643 case EL_SIEB_VOLL: return GFX_SIEB_VOLL;
2644 case EL_SIEB_TOT: return GFX_SIEB_TOT;
2645 case EL_SALZSAEURE: return GFX_SALZSAEURE;
2646 case EL_AMOEBE_TOT: return GFX_AMOEBE_TOT;
2647 case EL_AMOEBE_NASS: return GFX_AMOEBE_NASS;
2648 case EL_AMOEBE_NORM: return GFX_AMOEBE_NORM;
2649 case EL_AMOEBE_VOLL: return GFX_AMOEBE_VOLL;
2650 case EL_AMOEBE_BD: return GFX_AMOEBE_BD;
2651 case EL_AMOEBA2DIAM: return GFX_AMOEBA2DIAM;
2652 case EL_KOKOSNUSS: return GFX_KOKOSNUSS;
2653 case EL_LIFE: return GFX_LIFE;
2654 case EL_LIFE_ASYNC: return GFX_LIFE_ASYNC;
2655 case EL_DYNAMIT: return GFX_DYNAMIT;
2656 case EL_BADEWANNE: return GFX_BADEWANNE;
2657 case EL_BADEWANNE1: return GFX_BADEWANNE1;
2658 case EL_BADEWANNE2: return GFX_BADEWANNE2;
2659 case EL_BADEWANNE3: return GFX_BADEWANNE3;
2660 case EL_BADEWANNE4: return GFX_BADEWANNE4;
2661 case EL_BADEWANNE5: return GFX_BADEWANNE5;
2662 case EL_ABLENK_AUS: return GFX_ABLENK_AUS;
2663 case EL_ABLENK_EIN: return GFX_ABLENK_EIN;
2664 case EL_SCHLUESSEL1: return GFX_SCHLUESSEL1;
2665 case EL_SCHLUESSEL2: return GFX_SCHLUESSEL2;
2666 case EL_SCHLUESSEL3: return GFX_SCHLUESSEL3;
2667 case EL_SCHLUESSEL4: return GFX_SCHLUESSEL4;
2668 case EL_PFORTE1: return GFX_PFORTE1;
2669 case EL_PFORTE2: return GFX_PFORTE2;
2670 case EL_PFORTE3: return GFX_PFORTE3;
2671 case EL_PFORTE4: return GFX_PFORTE4;
2672 case EL_PFORTE1X: return GFX_PFORTE1X;
2673 case EL_PFORTE2X: return GFX_PFORTE2X;
2674 case EL_PFORTE3X: return GFX_PFORTE3X;
2675 case EL_PFORTE4X: return GFX_PFORTE4X;
2676 case EL_DYNAMIT_AUS: return GFX_DYNAMIT_AUS;
2677 case EL_PACMAN: return GFX_PACMAN;
2678 case EL_PACMAN_R: return GFX_PACMAN_R;
2679 case EL_PACMAN_O: return GFX_PACMAN_O;
2680 case EL_PACMAN_L: return GFX_PACMAN_L;
2681 case EL_PACMAN_U: return GFX_PACMAN_U;
2682 case EL_UNSICHTBAR: return GFX_UNSICHTBAR;
2683 case EL_ERZ_EDEL: return GFX_ERZ_EDEL;
2684 case EL_ERZ_DIAM: return GFX_ERZ_DIAM;
2685 case EL_BIRNE_AUS: return GFX_BIRNE_AUS;
2686 case EL_BIRNE_EIN: return GFX_BIRNE_EIN;
2687 case EL_ZEIT_VOLL: return GFX_ZEIT_VOLL;
2688 case EL_ZEIT_LEER: return GFX_ZEIT_LEER;
2689 case EL_MAUER_LEBT: return GFX_MAUER_LEBT;
2690 case EL_MAUER_X: return GFX_MAUER_X;
2691 case EL_MAUER_Y: return GFX_MAUER_Y;
2692 case EL_MAUER_XY: return GFX_MAUER_XY;
2693 case EL_EDELSTEIN_BD: return GFX_EDELSTEIN_BD;
2694 case EL_EDELSTEIN_GELB: return GFX_EDELSTEIN_GELB;
2695 case EL_EDELSTEIN_ROT: return GFX_EDELSTEIN_ROT;
2696 case EL_EDELSTEIN_LILA: return GFX_EDELSTEIN_LILA;
2697 case EL_ERZ_EDEL_BD: return GFX_ERZ_EDEL_BD;
2698 case EL_ERZ_EDEL_GELB: return GFX_ERZ_EDEL_GELB;
2699 case EL_ERZ_EDEL_ROT: return GFX_ERZ_EDEL_ROT;
2700 case EL_ERZ_EDEL_LILA: return GFX_ERZ_EDEL_LILA;
2701 case EL_MAMPFER2: return GFX_MAMPFER2;
2702 case EL_SIEB2_INAKTIV: return GFX_SIEB2_INAKTIV;
2703 case EL_SIEB2_LEER: return GFX_SIEB2_LEER;
2704 case EL_SIEB2_VOLL: return GFX_SIEB2_VOLL;
2705 case EL_SIEB2_TOT: return GFX_SIEB2_TOT;
2706 case EL_DYNABOMB: return GFX_DYNABOMB;
2707 case EL_DYNABOMB_NR: return GFX_DYNABOMB_NR;
2708 case EL_DYNABOMB_SZ: return GFX_DYNABOMB_SZ;
2709 case EL_DYNABOMB_XL: return GFX_DYNABOMB_XL;
2710 case EL_SOKOBAN_OBJEKT: return GFX_SOKOBAN_OBJEKT;
2711 case EL_SOKOBAN_FELD_LEER: return GFX_SOKOBAN_FELD_LEER;
2712 case EL_SOKOBAN_FELD_VOLL: return GFX_SOKOBAN_FELD_VOLL;
2713 case EL_MAULWURF: return GFX_MAULWURF;
2714 case EL_PINGUIN: return GFX_PINGUIN;
2715 case EL_SCHWEIN: return GFX_SCHWEIN;
2716 case EL_DRACHE: return GFX_DRACHE;
2717 case EL_SONDE: return GFX_SONDE;
2718 case EL_PFEIL_L: return GFX_PFEIL_L;
2719 case EL_PFEIL_R: return GFX_PFEIL_R;
2720 case EL_PFEIL_O: return GFX_PFEIL_O;
2721 case EL_PFEIL_U: return GFX_PFEIL_U;
2722 case EL_SPEED_PILL: return GFX_SPEED_PILL;
2723 case EL_SP_TERMINAL_ACTIVE: return GFX_SP_TERMINAL;
2724 case EL_SP_BUG_ACTIVE: return GFX_SP_BUG_ACTIVE;
2725 case EL_INVISIBLE_STEEL: return GFX_INVISIBLE_STEEL;
2726 case EL_BLACK_ORB: return GFX_BLACK_ORB;
2730 if (IS_CHAR(element))
2731 return GFX_CHAR_START + (element - EL_CHAR_START);
2732 else if (element >= EL_SP_START && element <= EL_SP_END)
2734 int nr_element = element - EL_SP_START;
2735 int gfx_per_line = 8;
2737 (nr_element / gfx_per_line) * MORE_PER_LINE +
2738 (nr_element % gfx_per_line);
2740 return GFX_START_ROCKSMORE + nr_graphic;